c# - IList<string> या IEnumerable<string> से अल्पविराम से अलग सूची बनाना




(14)

IList<string> या IEnumerable<string> से स्ट्रिंग मानों की अल्पविराम से अलग सूची बनाने का सबसे साफ तरीका क्या है?

String.Join(...) एक string[] पर चल रहा है string[] ताकि IList<string> या IEnumerable<string> जैसे प्रकारों को आसानी से स्ट्रिंग सरणी में परिवर्तित नहीं किया जा सकता है, के साथ काम करने के लिए बोझिल हो सकता है।


FYI, string.Join() के .NET 4.0 संस्करण में कुछ अतिरिक्त ओवरलोड हैं , जो कि केवल सरणी के बजाय string.Join() साथ काम करते हैं, जिसमें किसी भी प्रकार से निपटने वाला T :

public static string Join(string separator, IEnumerable<string> values)
public static string Join<T>(string separator, IEnumerable<T> values)

आप Lists और .ToArray() पर .ToArray() उपयोग कर सकते हैं, और उसके बाद .ToArray() उपयोग कर सकते हैं जैसा आप चाहते थे।


इस चर्चा के लिए थोड़ा देर हो रही है लेकिन यह मेरा योगदान है fwiw। मेरे पास एक IList<Guid> OrderIds को एक CSV स्ट्रिंग में परिवर्तित करने के लिए है लेकिन निम्नलिखित सामान्य है और अन्य प्रकारों के साथ असम्बद्ध काम करता है:

string csv = OrderIds.Aggregate(new StringBuilder(),
             (sb, v) => sb.Append(v).Append(","),
             sb => {if (0 < sb.Length) sb.Length--; return sb.ToString();});

लघु और मीठा, नई स्ट्रिंग बनाने के लिए स्ट्रिंगबिल्डर का उपयोग करता है, अंतिम कॉमा को हटाने और CSV स्ट्रिंग को वापस करने के लिए स्ट्रिंगबिल्डर लंबाई को एक से घटा देता है।

मैंने इसे स्ट्रिंग + कॉमा जोड़ने के लिए एकाधिक Append() उपयोग के लिए अपडेट किया है। जेम्स की प्रतिक्रिया से मैंने स्ट्रिंगबिल्डर का उपयोग करने के लिए परावर्तक का उपयोग किया। StringBuilder.AppendFormat()AppendFormat() को स्ट्रिंगबिल्डर का उपयोग प्रारूप स्ट्रिंग बनाने के लिए करता है जो एकाधिक Appends() उपयोग से इस संदर्भ में इसे कम कुशल बनाता है।


उन्हें .NET 3.5 में लिंक एक्सटेंशन का उपयोग करके आसानी से सरणी में परिवर्तित किया जा सकता है।

   var stringArray = stringList.ToArray();

ऐसा करने का सबसे आसान तरीका यह है कि LINQ Aggregate विधि का उपयोग कर रहा है:

string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)

कुछ थोड़ा फगली है, लेकिन यह काम करता है:

string divisionsCSV = String.Join(",", ((List<IDivisionView>)divisions).ConvertAll<string>(d => d.DivisionID.ToString("b")).ToArray());

आपको कनवर्टर देने के बाद आपको एक सूची से सीएसवी देता है (इस मामले में डी => डी। डिविजनआईड.ओस्ट्रिंग ("बी"))।

हैकी लेकिन काम करता है - शायद एक विस्तार विधि में बनाया जा सकता है?


जिस तरह से मैंने इसे किया है, वैसे ही मैंने इसे अन्य भाषाओं में किया है:

private string ToStringList<T>(IEnumerable<T> list, string delimiter)
{
  var sb = new StringBuilder();
  string separator = String.Empty;
  foreach (T value in list)
  {
    sb.Append(separator).Append(value);
    separator = delimiter;
  }
  return sb.ToString();
}

दूसरों द्वारा सूचीबद्ध तरीकों में से किसी एक का उपयोग करके आप किसी सरणी में परिवर्तित होने के बाद निम्न की तरह कुछ भी उपयोग कर सकते हैं:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Configuration;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            CommaDelimitedStringCollection commaStr = new CommaDelimitedStringCollection();
            string[] itemList = { "Test1", "Test2", "Test3" };
            commaStr.AddRange(itemList);
            Console.WriteLine(commaStr.ToString()); //Outputs Test1,Test2,Test3
            Console.ReadLine();
        }
    }
}

संपादित करें: Here एक और उदाहरण है


मुझे लगता है कि स्ट्रिंग मानों की अल्पविराम से अलग सूची बनाने का सबसे साफ तरीका बस है:

string.Join<string>(",", stringEnumerable);

यहां एक पूर्ण उदाहरण है:

IEnumerable<string> stringEnumerable= new List<string>();
stringList.Add("Comma");
stringList.Add("Separated");

string.Join<string>(",", stringEnumerable);

एक सहायक समारोह बनाने की कोई आवश्यकता नहीं है, यह .NET 4.0 और उसके बाद में बनाया गया है।


मेरा जवाब उपर्युक्त समाधान की तरह है लेकिन कम कॉल-स्टैक भारी होना चाहिए क्योंकि कोई स्पष्ट प्रतिनिधि कॉल नहीं है:

public static string ToCommaDelimitedString<T>(this IEnumerable<T> items)
{
    StringBuilder sb = new StringBuilder();
    foreach (var item in items)
    {
        sb.Append(item.ToString());
        sb.Append(',');
    }
    if (sb.Length >= 1) sb.Length--;
    return sb.ToString();
}

बेशक, कोई डिलीमीटर-स्वतंत्र होने के लिए हस्ताक्षर का विस्तार कर सकता है। मैं वास्तव में sb.Remove () कॉल का प्रशंसक नहीं हूं और मैं इसे एक आईनेमरेबल पर एक लूप-अप-लूप होने के लिए रीफैक्टर करना चाहता हूं और यह निर्धारित करने के लिए MoveNext () का उपयोग करता हूं कि यह कॉमा लिखना है या नहीं। अगर मैं उस पर आऊंगा तो मैं चारों ओर झुकाऊंगा और उस समाधान को पोस्ट करूंगा।

यहां मैं वही चाहता हूं जो मैं चाहता था:

public static string ToDelimitedString<T>(this IEnumerable<T> source, string delimiter, Func<T, string> converter)
{
    StringBuilder sb = new StringBuilder();
    var en = source.GetEnumerator();
    bool notdone = en.MoveNext();
    while (notdone)
    {
        sb.Append(converter(en.Current));
        notdone = en.MoveNext();
        if (notdone) sb.Append(delimiter);
    }
    return sb.ToString();
}

कोई अस्थायी सरणी या सूची भंडारण आवश्यक नहीं है और कोई Length-- Remove() या Length-- हैक आवश्यक है।

मेरे ढांचे पुस्तकालय में मैंने इस विधि हस्ताक्षर पर कुछ बदलाव किए हैं, क्रमशः "," और x.ToString() उपयोग के साथ x.ToString() और converter पैरामीटर सहित प्रत्येक संयोजन को डिफ़ॉल्ट रूप से।


मैंने इसे करने के लिए कुछ विस्तार विधियों को लिखा है जो कुशल हैं:

    public static string JoinWithDelimiter(this IEnumerable<String> that, string delim) {
        var sb = new StringBuilder();
        foreach (var s in that) {
            sb.AppendToList(s,delim);
        }

        return sb.ToString();
    }

यह इस पर निर्भर करता है

    public static string AppendToList(this String s, string item, string delim) {
        if (s.Length == 0) {
            return item;
        }

        return s+delim+item;
    }

यहां एक और विस्तार विधि है:

    public static string Join(this IEnumerable<string> source, string separator)
    {
        return string.Join(separator, source);
    }

स्ट्रिंग्स में शामिल होने के लिए एक अच्छी सी # विधि खोजते समय मैं इस चर्चा पर आया था जैसे कि यह MySQL विधि CONCAT_WS() साथ किया जाता है। यह विधि string.Join() विधि से अलग है जिसमें स्ट्रिंग नल या खाली हैं, तो यह विभाजक चिह्न नहीं जोड़ता है।

CONCAT_WS (',', tbl.Lastname, tbl.Firstname)

अगर Lastname नाम खाली है, तो केवल Lastname नाम Lastname , जबकि

string.Join (",", strLastname, strFirstname)

उसी मामले में strLastname + ", " वापस आ जाएगा।

पहला व्यवहार चाहते हैं, मैंने निम्नलिखित विधियों को लिखा है:

    public static string JoinStringsIfNotNullOrEmpty(string strSeparator, string strA, string strB, string strC = "")
    {
        return JoinStringsIfNotNullOrEmpty(strSeparator, new[] {strA, strB, strC});
    }

    public static string JoinStringsIfNotNullOrEmpty(string strSeparator, string[] arrayStrings)
    {
        if (strSeparator == null)
            strSeparator = "";
        if (arrayStrings == null)
            return "";
        string strRetVal = arrayStrings.Where(str => !string.IsNullOrEmpty(str)).Aggregate("", (current, str) => current + (str + strSeparator));
        int trimEndStartIndex = strRetVal.Length - strSeparator.Length;
        if (trimEndStartIndex>0)
            strRetVal = strRetVal.Remove(trimEndStartIndex);
        return strRetVal;
    }

हमारे पास एक उपयोगिता कार्य है, ऐसा कुछ है:

public static string Join<T>( string delimiter, 
    IEnumerable<T> collection, Func<T, string> convert )
{
    return string.Join( delimiter, 
        collection.Select( convert ).ToArray() );
}

कई संग्रहों को आसानी से शामिल करने के लिए किसका उपयोग किया जा सकता है:

int[] ids = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233};

string csv = StringUtility.Join(",", ids, i => i.ToString() );

ध्यान दें कि हमारे पास लैम्ब्डा से पहले संग्रह पैरामीटर है क्योंकि इंटेलिजेंस तब संग्रह प्रकार को उठाता है।

यदि आपके पास पहले से तारों की गणना है तो आपको केवल ToArray करना है:

string csv = string.Join( ",", myStrings.ToArray() );




string