Como juntar int a uma string separada por caracteres no .NET?

Eu tenho uma matriz de inteiros:

int[] number = new int[] { 2,3,6,7 }; 

Qual é a maneira mais fácil de converter estes em uma única string onde os números são separados por um caractere (como: "2,3,6,7" )?

Eu estou em c # e .NET 3.5.

 var ints = new int[] {1, 2, 3, 4, 5}; var result = string.Join(",", ints.Select(x => x.ToString()).ToArray()); Console.WriteLine(result); // prints "1,2,3,4,5" 

EDITAR :

Eu vejo várias soluções anunciam o uso de StringBuilder. Alguém queixas que o método Join deve ter um argumento IEnumerable.

Eu vou decepcioná-lo 🙂 String.Join requer matriz por um único motivo – desempenho. O método Join precisa saber o tamanho dos dados para pré-alocar efetivamente a quantidade necessária de memory.

Aqui está uma parte da implementação interna do método String.Join:

 // length computed from length of items in input array and length of separator string str = FastAllocateString(length); fixed (char* chRef = &str.m_firstChar) // note than we use direct memory access here { UnSafeCharBuffer buffer = new UnSafeCharBuffer(chRef, length); buffer.AppendString(value[startIndex]); for (int j = startIndex + 1; j <= num2; j++) { buffer.AppendString(separator); buffer.AppendString(value[j]); } } 

Estou com preguiça de comparar o desempenho dos methods sugeridos. Mas algo me diz que Join vai ganhar 🙂

Embora o OP tenha especificado o .NET 3.5, as pessoas que desejam fazer isso no .NET 2.0 com C # 2 podem fazer isso:

 string.Join(",", Array.ConvertAll(ints, Convert.ToString)); 

Eu acho que há um número de outros casos em que o uso das funções Convert.xxx é uma alternativa mais pura para um lambda, embora em C # 3 o lambda possa ajudar na inferência de tipos.

Uma versão C # 3 razoavelmente compacta que funciona com o .NET 2.0 é esta:

 string.Join(",", Array.ConvertAll(ints, item => item.ToString())) 

Uma mistura das duas abordagens seria escrever um método de extensão no IEnumerable que usava um StringBuilder. Aqui está um exemplo, com sobrecargas diferentes dependendo se você deseja especificar a transformação ou apenas confiar em ToString simples. Eu nomeei o método “JoinStrings” em vez de “Join” para evitar confusão com o outro tipo de Join. Talvez alguém possa inventar um nome melhor 🙂

 using System; using System.Collections.Generic; using System.Text; public static class Extensions { public static string JoinStrings(this IEnumerable source, Func projection, string separator) { StringBuilder builder = new StringBuilder(); bool first = true; foreach (T element in source) { if (first) { first = false; } else { builder.Append(separator); } builder.Append(projection(element)); } return builder.ToString(); } public static string JoinStrings(this IEnumerable source, string separator) { return JoinStrings(source, t => t.ToString(), separator); } } class Test { public static void Main() { int[] x = {1, 2, 3, 4, 5, 10, 11}; Console.WriteLine(x.JoinStrings(";")); Console.WriteLine(x.JoinStrings(i => i.ToString("X"), ",")); } } 
 String.Join(";", number.Select(item => item.ToString()).ToArray()); 

Nós temos que converter cada um dos itens para uma String antes de podermos nos juntar a eles, então faz sentido usar Select e uma expressão lambda. Isso é equivalente a map em outros idiomas. Então temos que converter a coleção resultante de string de volta para um array, porque String.Join só aceita um array de string.

O ToArray() é um pouco feio, eu acho. String.Join deve realmente aceitar IEnumerable , não há razão para restringi-lo a apenas arrays. Isso é provavelmente apenas porque Join é de antes dos genéricos, quando os arrays eram o único tipo de coleção typescript disponível.

Se a sua matriz de inteiros pode ser grande, você obterá um desempenho melhor usando um StringBuilder. Por exemplo:

 StringBuilder builder = new StringBuilder(); char separator = ','; foreach(int value in integerArray) { if (builder.Length > 0) builder.Append(separator); builder.Append(value); } string result = builder.ToString(); 

Edit: Quando eu postei isso, eu estava sob a impressão equivocada de que “StringBuilder.Append (int valor)” internamente gerenciado para acrescentar a representação de seqüência de caracteres do valor inteiro sem criar um object de seqüência de caracteres. Isso está errado: inspecionar o método com o Reflector mostra que ele simplesmente acrescenta value.ToString ().

Portanto, a única diferença de desempenho potencial é que essa técnica evita a criação de uma matriz e libera as sequências de garbage collection um pouco mais cedo. Na prática, isso não fará nenhuma diferença mensurável, por isso inventei essa melhor solução .

A questão é “a maneira mais fácil de converter estes em uma única string onde o número é separado por um caractere”.

A maneira mais fácil é:

 int[] numbers = new int[] { 2,3,6,7 }; string number_string = string.Join(",", numbers); // do whatever you want with your exciting new number string 

EDIT: Isso só funciona no .NET 4.0 +, eu perdi o requisito do .NET 3.5 na primeira vez que li a pergunta.

Eu concordo com a expressão lambda para legibilidade e facilidade de manutenção, mas nem sempre será a melhor opção. A desvantagem de usar as abordagens IEnumerable / ToArray e StringBuilder é que elas precisam aumentar dinamicamente uma lista, seja de itens ou caracteres, pois não sabem quanto espaço será necessário para a sequência final.

Se o raro caso em que a velocidade é mais importante que a concisão, o seguinte é mais eficiente.

 int[] number = new int[] { 1, 2, 3, 4, 5 }; string[] strings = new string[number.Length]; for (int i = 0; i < number.Length; i++) strings[i] = number[i].ToString(); string result = string.Join(",", strings); 
 ints.Aggregate("", ( str, n ) => str +","+ n ).Substring(1); 

Eu também achei que havia um jeito mais simples. Não sabe sobre desempenho, alguém tem alguma idéia (teórica)?

No .NET 4.0, a junit de strings tem uma sobrecarga para params object[] , então é tão simples quanto:

 int[] ids = new int[] { 1, 2, 3 }; string.Join(",", ids); 

exemplo

 int[] ids = new int[] { 1, 2, 3 }; System.Data.Common.DbCommand cmd = new System.Data.SqlClient.SqlCommand("SELECT * FROM some_table WHERE id_column IN (@bla)"); cmd.CommandText = cmd.CommandText.Replace("@bla", string.Join(",", ids)); 

No .NET 2.0, é um pouquinho mais difícil, já que não há essa sobrecarga. Então você precisa do seu próprio método genérico:

 public static string JoinArray(string separator, T[] inputTypeArray) { string strRetValue = null; System.Collections.Generic.List ls = new System.Collections.Generic.List(); for (int i = 0; i < inputTypeArray.Length; ++i) { string str = System.Convert.ToString(inputTypeArray[i], System.Globalization.CultureInfo.InvariantCulture); if (!string.IsNullOrEmpty(str)) { // SQL-Escape // if (typeof(T) == typeof(string)) // str = str.Replace("'", "''"); ls.Add(str); } // End if (!string.IsNullOrEmpty(str)) } // Next i strRetValue= string.Join(separator, ls.ToArray()); ls.Clear(); ls = null; return strRetValue; } 

No .NET 3.5, você pode usar methods de extensão:

 public static class ArrayEx { public static string JoinArray(this T[] inputTypeArray, string separator) { string strRetValue = null; System.Collections.Generic.List ls = new System.Collections.Generic.List(); for (int i = 0; i < inputTypeArray.Length; ++i) { string str = System.Convert.ToString(inputTypeArray[i], System.Globalization.CultureInfo.InvariantCulture); if (!string.IsNullOrEmpty(str)) { // SQL-Escape // if (typeof(T) == typeof(string)) // str = str.Replace("'", "''"); ls.Add(str); } // End if (!string.IsNullOrEmpty(str)) } // Next i strRetValue= string.Join(separator, ls.ToArray()); ls.Clear(); ls = null; return strRetValue; } } 

Então você pode usar o método de extensão JoinArray.

 int[] ids = new int[] { 1, 2, 3 }; string strIdList = ids.JoinArray(","); 

Você também pode usar esse método de extensão no .NET 2.0, se você adicionar o ExtensionAttribute ao seu código:

 // you need this once (only), and it must be in this namespace namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] public sealed class ExtensionAttribute : Attribute {} } 

Você pode fazer

 ints.ToString(",") ints.ToString("|") ints.ToString(":") 

Confira

ToString Delimitado por Separador para Matriz, Lista, Dicionário, IEnumerável Genérico