string.Join на List <int> или другом типе

86

Я хочу превратить массив или список целых чисел в строку с разделителями-запятыми, например:

string myFunction(List<int> a) {
    return string.Join(",", a);
}

Но string.Join принимает только List<string>второй параметр. Как лучше всего это сделать?

Code Commander
источник
2
Какую версию C # / .NET вы используете?
Марк Байерс,
Возможный дубликат stackoverflow.com/questions/3211422/…
goodeye

Ответы:

149

Лучший способ - перейти на .NET 4.0, где есть перегрузка, которая делает то, что вы хотите:

Если вы не можете обновить, вы можете добиться того же эффекта, используя Select и ToArray.

    return string.Join(",", a.Select(x => x.ToString()).ToArray());
Марк Байерс
источник
Также предполагает, что он по крайней мере на C # 3, .NET 3.5
Энтони Пеграм
Зачем использовать LINQ вместо встроенного ToArrayметода List<T>?
Стивен Судит,
2
потому что у него будет List <int>. Linq select преобразует List <int> в IEnumerable <string>, а затем в массив.
Грег Богумил,
Обновление до 4.0 в моей ситуации нецелесообразно, но решение LINQ - это именно то, что я искал. Благодарность!
Code Commander
1
@gbogumil: Простите, не заметил, что это int.
Стивен Судит
5

Масштабируемый и безопасный реализация родовых перечислимых строк объединяются для .NET 3.5. Итераторы используются для того, чтобы значение строки соединения не застревало в конце строки. Он корректно работает с 0, 1 и более элементами:

public static class StringExtensions
{
    public static string Join<T>(this string joinWith, IEnumerable<T> list)
    {
        if (list == null)
            throw new ArgumentNullException("list");
        if (joinWith == null)
            throw new ArgumentNullException("joinWith");

        var stringBuilder = new StringBuilder();
        var enumerator = list.GetEnumerator();

        if (!enumerator.MoveNext())
            return string.Empty;

        while (true)
        {
            stringBuilder.Append(enumerator.Current);
            if (!enumerator.MoveNext())
                break;

            stringBuilder.Append(joinWith);
        }

        return stringBuilder.ToString();
    }
}

Применение:

var arrayOfInts = new[] { 1, 2, 3, 4 };
Console.WriteLine(",".Join(arrayOfInts));

var listOfInts = new List<int> { 1, 2, 3, 4 };
Console.WriteLine(",".Join(listOfInts));

Наслаждайтесь!

Удалено
источник
+1: Это мой предпочтительный способ до .NET 4.0. Гораздо более масштабируемый, чем создание полностью нового массива строк из списка целых чисел, чтобы его String.Join(String, String[])можно было вызвать. Единственное, что я бы сказал, это то, что необычно видеть этот метод, написанный как расширение, Stringв отличие от IEnumerable<String>- я склонен всегда вызывать его в конце длинной цепочки вызовов методов расширения.
Алекс Хамфри
2
Я украл идею у Python, если это поможет!
Удалено
4

.NET 2.0:

static string IntListToDelimitedString(List<int> intList, char Delimiter)
{
    StringBuilder builder = new StringBuilder();

    for (int i = 0; i < intList.Count; i++)
    {
        builder.Append(intList[i].ToString());

        if (i != intList.Count - 1)
            builder.Append(Delimiter);
    }

    return builder.ToString();
}
Кайл Розендо
источник
3
Хороший подход 2.0. Возможно, вы захотите сделать присоединяемый символ параметром, а не жестко закодировать его в методе.
Энтони Пеграм,
Типичная оптимизация - добавить разделитель без проверки, а затем удалить последний символ после выхода из цикла.
Стивен Судит,
@Steven - Я думал об этом, но я думаю, что это также будет зависеть от длины строки (без тестирования я не уверен), поэтому я придерживался простой проверки bool.
Кайл Розендо
Я подозреваю, что оптимизацию можно будет измерить только для длинных строк. Сказав это, я не думаю, что это будет медленнее даже для коротких.
Стивен Судит,
3

У меня был аналогичный метод расширения, который я изменил на этот

public static class MyExtensions
{
    public static string Join(this List<int> a, string splitChar)
    {
        return string.Join(splitChar, a.Select(n => n.ToString()).ToArray());
    }
}

и вы используете это так

var test = new List<int>() { 1, 2, 3, 4, 5 };
string s = test.Join(",");

.NET 3.5

Йонас Эльфстрём
источник
Не уверен, что мне это нравится. IEnumerable<T>у него уже есть Joinметод, и этот новый метод выполняет совершенно другую операцию, что делает его использование нелогичным. Во- вторых, если вы были намерены создать этот метод, идти вперед и сделать это в общем применимо.
Энтони Пеграм,
Это хитрость, имитирующая метод соединения массивов в Ruby. ruby-doc.org/core/classes/Array.html#M002182
Йонас Эльфстрём,
Кроме того .ToString () не всегда возвращает строковое представление T, поэтому я предполагаю, что это действительно может вызвать некоторую путаницу.
Йонас Эльфстрём,
2

Этот ответ для вас, если вы пока не хотите углубляться в глубины .NET 4.0.

String.Join () объединяет все элементы массива строк, используя указанный разделитель между каждым элементом.

Синтаксис:

public static string Join(
    string separator,
    params string[] value
)

Вместо того, чтобы передавать ваш список целых чисел методу Join, я предлагаю сначала создать массив строк.

Вот что я предлагаю:

static string myFunction(List<int> a) {
    int[] intArray = a.ToArray();
    string[] stringArray = new string[intArray.Length];

    for (int i = 0; i < intArray.Length; i++)
    {
        stringArray[i] = intArray[i].ToString();
    }

    return string.Join(",", stringArray);
}
Грег
источник
3
Это достойный подход, если кто-то все еще использует 2.0. Однако в intArrayэтом нет необходимости. List<int>индексируется и имеет Countсвойство, делающее преобразование в массив излишним. Вы также можете сделать присоединяемый символ параметром, а не жестко кодировать его в методе.
Энтони Пеграм,
2

Использование .NET 4.0

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string s = myFunction(PopulateTestList());
        this.TextBox1.Text = s;
    }

    protected List<int> PopulateTestList()
    {
        List<int> thisList = new List<int>();
        thisList.Add(22);
        thisList.Add(33);
        thisList.Add(44);

        return thisList;
    }

    protected string myFunction(List<int> a)
    {
        return string.Join(",", a);
    }
}
user436001
источник
2

В .NET у класса списка есть .ToArray()метод. Что-то вроде этого могло сработать:

string myFunction(List<int> a)
{
    return string.Join(",", a.ToArray());
}

Ссылка: Список <T> методов (MSDN)

Wintoch
источник
Здесь answer from 2010уже сказано, что, как ToStringподразумевается при выполнении string.Join.
Miller