Создание списка через запятую из IList <string>или IEnumerable <string> - PullRequest
759 голосов
/ 28 апреля 2009

Каков самый чистый способ создания списка строковых значений через запятую из IList<string> или IEnumerable<string>?

String.Join(...) работает на string[], поэтому может быть неудобно работать, когда такие типы, как IList<string> или IEnumerable<string>, не могут быть легко преобразованы в строковый массив.

Ответы [ 21 ]

7 голосов
/ 05 июля 2010

Что-то немного глупо, но это работает:

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

Дает вам CSV из списка после того, как вы передали ему конвертор (в данном случае d => d.DivisionID.ToString ("b")).

Хак, но работает - может быть, можно сделать метод расширения?

4 голосов
/ 28 апреля 2009

У нас есть служебная функция, примерно такая:

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() );

Обратите внимание, что у нас есть параметр коллекции до лямбды, потому что intellisense затем выбирает тип коллекции.

Если у вас уже есть перечисление строк, все, что вам нужно сделать, это ToArray:

string csv = string.Join( ",", myStrings.ToArray() );
3 голосов
/ 25 ноября 2015

Я пришел к этому обсуждению, когда искал хороший метод C # для объединения строк, как это делается с методом MySql CONCAT_WS(). Этот метод отличается от метода string.Join() тем, что он не добавляет знак разделителя, если строки пустые или пустые.

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

вернет только 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;
    }
3 голосов
/ 12 ноября 2013

Я только что решил эту проблему, прежде чем обсуждать эту статью. Мое решение выглядит примерно так:

   private static string GetSeparator<T>(IList<T> list, T item)
   {
       return (list.IndexOf(item) == list.Count - 1) ? "" : ", ";
   }

Называется как:

List<thing> myThings;
string tidyString;

foreach (var thing in myThings)
{
     tidyString += string.format("Thing {0} is a {1}", thing.id, thing.name) + GetSeparator(myThings, thing);
}

Я мог бы так же легко выразиться как таковой и был бы более эффективным:

string.Join(“,”, myThings.Select(t => string.format(“Thing {0} is a {1}”, t.id, t.name)); 
3 голосов
/ 12 апреля 2013

Надеюсь, это самый простой способ

 string Commaseplist;
 string[] itemList = { "Test1", "Test2", "Test3" };
 Commaseplist = string.join(",",itemList);
 Console.WriteLine(Commaseplist); //Outputs Test1,Test2,Test3
3 голосов
/ 28 апреля 2009

вы можете преобразовать IList в массив, используя ToArray, а затем запустить команду string.join для массива.

Dim strs As New List(Of String)
Dim arr As Array
arr = strs.ToArray
3 голосов
/ 22 июня 2010

Мой ответ такой же, как и выше. Агрегированное решение, но оно должно быть менее сложным, так как нет явных вызовов делегатов:

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 (), и я хотел бы изменить его на прямой цикл while над IEnumerable и использовать 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();
}

Не требуется временный массив или хранилище списков и не требуется взлом StringBuilder Remove() или Length--.

В моей фреймворковой библиотеке я сделал несколько вариаций сигнатуры этого метода, каждая комбинация включала параметры delimiter и converter с использованием "," и x.ToString() в качестве значений по умолчанию, соответственно.

3 голосов
/ 28 апреля 2009

Их можно легко преобразовать в массив с помощью расширений Linq в .NET 3.5.

   var stringArray = stringList.ToArray();
3 голосов
/ 23 июля 2009

Вы также можете использовать что-то вроде следующего после преобразования его в массив, используя один из методов, перечисленных другими:

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();
        }
    }
}

Редактировать: Здесь является еще одним примером

2 голосов
/ 28 апреля 2009

Вы можете использовать .ToArray() на Lists и IEnumerables, а затем использовать String.Join(), как вы хотели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...