string.Junte-se a uma lista <int> ou outro tipo

86

Quero transformar uma matriz ou lista de ints em uma string delimitada por vírgulas, como esta:

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

Mas string.Join leva apenas List<string>como segundo parâmetro. Qual é a melhor maneira de fazer isso?

Code Commander
fonte
2
Qual versão do C # / .NET você está usando?
Mark Byers
Possível duplicata de stackoverflow.com/questions/3211422/…
goodeye

Respostas:

149

A melhor maneira é atualizar para .NET 4.0, onde há uma sobrecarga que faz o que você deseja:

Se você não pode atualizar, você pode obter o mesmo efeito usando Select e ToArray.

    return string.Join(",", a.Select(x => x.ToString()).ToArray());
Mark Byers
fonte
Também presume que ele esteja pelo menos em C # 3, .NET 3.5
Anthony Pegram
Por que usar LINQ em vez do ToArraymétodo interno de List<T>?
Steven Sudit
2
porque ele teria uma Lista <int>. O linq select converte List <int> em IEnumerable <string> e depois na matriz.
Greg Bogumil
Atualizar para 4.0 não é prático na minha situação, mas a solução LINQ é exatamente o que eu estava procurando. Obrigado!
Code Commander
1
@gbogumil: Desculpe, não percebi que era um int.
Steven Sudit
5

Uma implementação escalonável e segura de uma junção de string enumerável genérica para .NET 3.5. O uso de iteradores é para que o valor da string de junção não fique preso no final da string. Funciona corretamente com 0, 1 e mais elementos:

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

Uso:

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

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

Aproveitar!

Excluído
fonte
+1: Esta é a minha forma preferida antes do .NET 4.0. Muito mais escalável do que produzir um array inteiramente novo de strings de uma lista de ints para que String.Join(String, String[])possa ser chamado. A única coisa que eu diria é que é incomum ver esse método escrito como uma extensão em Stringvez de IEnumerable<String>- eu costumo sempre chamá-lo no final de uma longa cadeia de chamadas de método de extensão.
Alex Humphrey
2
Eu roubei a ideia do Python, se isso ajudar!
Excluído em
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
fonte
3
Uma boa abordagem 2.0. Você pode querer tornar o caractere de junção um parâmetro em vez de codificá-lo no método.
Anthony Pegram
Uma otimização típica é anexar o delimitador sem testar e, em seguida, remover o último caractere assim que sair do loop.
Steven Sudit
@Steven - Eu estava pensando sobre isso, mas acho que isso também dependeria do comprimento da corda (sem testar, não tenho certeza), então me limitei à verificação simples do bool.
Kyle Rosendo
Suspeito que a otimização só seria mensurável para strings longas. Dito isso, não acho que seria mais lento, mesmo para os mais curtos.
Steven Sudit
2

Esta resposta é para você se você não quiser se aventurar nas profundezas do .NET 4.0 ainda.

String.Join () concatena todos os elementos de uma matriz de string, usando o separador especificado entre cada elemento.

A sintaxe é

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

Em vez de passar sua List of ints para o método Join, sugiro construir primeiro um array de strings.

Aqui está o que proponho:

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
fonte
3
Esta é uma abordagem decente se alguém ainda estiver no 2.0. Porém, intArrayé desnecessário. List<int>é indexável e tem uma Countpropriedade, tornando a conversão para um array supérflua. Você também pode querer tornar o caractere de junção um parâmetro, em vez de codificá-lo no método.
Anthony Pegram
2

Tinha um método de extensão semelhante que modifiquei para este

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

e você usa assim

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

.NET 3.5

Jonas Elfström
fonte
Não tenho certeza se gosto disso. IEnumerable<T>já tem um Joinmétodo, e este novo método realiza uma operação completamente diferente, tornando seu uso contra-intuitivo. Em segundo lugar, se você fosse criar esse método, vá em frente e torne-o genericamente aplicável.
Anthony Pegram
É um hack que imita o método join em arrays em Ruby. ruby-doc.org/core/classes/Array.html#M002182
Jonas Elfström
Além disso, .ToString () nem sempre retorna uma representação de string de T, então acho que isso pode realmente causar alguma confusão.
Jonas Elfström
2

Usando .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
fonte
2

Em .NET, a classe de lista tem um .ToArray()método. Algo assim pode funcionar:

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

Ref: Listar métodos <T> (MSDN)

Wintoch
fonte
Isso answer from 2010já afirma que, como ToStringestá implícito ao fazer a string.Join.
Miller