string.Join on a List <int> lub inny typ

86

Chcę zamienić tablicę lub listę int na ciąg rozdzielany przecinkami, na przykład:

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

Ale string.Join przyjmuje tylko List<string>jako drugi parametr. Jaki jest najlepszy sposób, aby to zrobić?

Code Commander
źródło
2
Której wersji C # / .NET używasz?
Mark Byers
Możliwy duplikat stackoverflow.com/questions/3211422/ ...
goodeye

Odpowiedzi:

149

Najlepszym sposobem jest uaktualnienie do .NET 4.0, gdzie występuje przeciążenie, które robi to, co chcesz:

Jeśli nie możesz zaktualizować, możesz osiągnąć ten sam efekt za pomocą funkcji Select i ToArray.

    return string.Join(",", a.Select(x => x.ToString()).ToArray());
Mark Byers
źródło
Zakłada również, że jest przynajmniej na C # 3, .NET 3.5
Anthony Pegram
Dlaczego warto używać LINQ zamiast wbudowanej ToArraymetody List<T>?
Steven Sudit
2
ponieważ miałby List <int>. Linq select konwertuje List <int> na IEnumerable <string>, a następnie do tablicy.
Greg Bogumil
Aktualizacja do wersji 4.0 nie jest praktyczna w mojej sytuacji, ale rozwiązanie LINQ jest dokładnie tym, czego szukałem. Dzięki!
Code Commander
1
@gbogumil: Przepraszamy, nie zauważyłem, że to plik int.
Steven Sudit
5

Skalowalne i bezpieczne wdrożenie generycznego przeliczalnego ciąg przyłączenia dla .NET 3.5. Użycie iteratorów polega na tym, że wartość łańcucha łączenia nie utknęła na końcu łańcucha. Działa poprawnie z 0, 1 i więcej elementami:

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

Stosowanie:

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

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

Cieszyć się!

Usunięto
źródło
+1: To jest mój preferowany sposób przed .NET 4.0. Znacznie bardziej skalowalne niż tworzenie zupełnie nowej tablicy ciągów z listy int, aby String.Join(String, String[])można ją było wywołać. Powiedziałbym tylko, że to niezwykłe widzieć tę metodę jako rozszerzenie, w Stringprzeciwieństwie do IEnumerable<String>- mam tendencję do wywoływania jej zawsze na końcu długiego łańcucha wywołań metod rozszerzających.
Alex Humphrey
2
Ukradłem ten pomysł z Pythona, jeśli to może pomóc!
Usunięto
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();
}
Kyle Rosendo
źródło
3
Dobre podejście 2.0. Możesz chcieć uczynić łączący znak parametrem, zamiast zakodować go na stałe w metodzie.
Anthony Pegram
Typowa optymalizacja polega na dodaniu separatora bez testowania, a następnie usunięciu ostatniego znaku po wyjściu z pętli.
Steven Sudit
@Steven - myślałem o tym, ale myślę, że to też zależałoby od długości struny (bez testów nie jestem pewien), więc utknąłem w prostym sprawdzeniu bool.
Kyle Rosendo
Podejrzewam, że optymalizacja byłaby mierzalna tylko w przypadku długich ciągów. Powiedziawszy to, nie sądzę, aby było to wolniejsze nawet dla krótkich.
Steven Sudit
3

Miał podobną metodę rozszerzenia, którą zmodyfikowałem do tego

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

i używasz tego w ten sposób

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

.NET 3.5

Jonas Elfström
źródło
Nie jestem pewien, czy mi się to podoba. IEnumerable<T>już ma Joinmetodę, a ta nowa metoda wykonuje zupełnie inną operację, przez co jej użycie jest sprzeczne z intuicją. Po drugie, jeśli były zamiar stworzyć tę metodę, należy iść dalej i uczynić go ogólnie dotyczy.
Anthony Pegram
To hack naśladujący metodę join w tablicach w Rubim. ruby-doc.org/core/classes/Array.html#M002182
Jonas Elfström
Ponadto .ToString () nie zawsze zwraca ciąg znaków reprezentujący T, więc myślę, że może to naprawdę spowodować pewne zamieszanie.
Jonas Elfström
2

Ta odpowiedź jest dla Ciebie, jeśli nie chcesz jeszcze zapuszczać się w głąb .NET 4.0.

String.Join () łączy wszystkie elementy tablicy ciągów, używając określonego separatora między każdym elementem.

Składnia to

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

Zamiast przekazywać Listę int do metody Join, proponuję najpierw zbudować tablicę ciągów.

Oto, co proponuję:

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);
}
Greg
źródło
3
To przyzwoite podejście, jeśli ktoś nadal jest na 2.0. Jednak nie intArrayjest to konieczne. List<int>jest indeksowalny i ma Countwłaściwość, przez co konwersja do tablicy jest zbędna. Możesz również chcieć, aby łączący znak był parametrem, zamiast zakodować go na stałe w metodzie.
Anthony Pegram
2

Korzystanie z .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
źródło
2

W .NET klasa listy ma .ToArray()metodę. Coś takiego mogłoby zadziałać:

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

Ref: List <T> Methods (MSDN)

wintoch
źródło
To answer from 2010już stwierdza, że, jak ToStringsugeruje się podczas wykonywania pliku string.Join.
Miller