рядок. Приєднуйтесь до List <int> або іншого типу


86

Я хочу перетворити масив або список ints на рядок, розділений комами, наприклад:

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

Але string.Join приймає лише List<string>другий параметр. Який найкращий спосіб це зробити?


2
Яку версію C # / .NET ви використовуєте?
Mark Byers

Можливий дублікат 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 перетворює List <int> у IEnumerable <string>, а потім у масив.
Грег Богуміл

Оновлення до 4.0 у моїй ситуації не є практичним, але рішення LINQ - це саме те, що я шукав. Дякую!
Командор кодексу

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. Набагато масштабніший, ніж створення цілком нового масиву рядків зі списку ints, щоб його 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.
Kyle Rosendo

Я підозрюю, що оптимізацію можна було б виміряти лише для довгих рядків. Сказавши це, я не думаю, що це буде повільніше навіть для коротких.
Стівен Судіт,

2

Ця відповідь для вас, якщо ви ще не хочете заглибитися в надра .NET 4.0.

String.Join () об'єднує всі елементи масиву рядків, використовуючи вказаний роздільник між кожним елементом.

Синтаксис є

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

Замість того, щоб передавати свій список ints методу 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

Мав подібний метод розширення, який я модифікував до цього

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.