TÃO rochas! Recebi essas 3 respostas excelentes em 10 minutos em um domingo!
Riri
4
A partir de .NET 4.0então, existem métodos que usam uma matriz de objetos e um IEnumerable para que você possa apenas fazer string.join(",", number). Eu sei que a pergunta especifica .NET 3.5, então não respondi, mas ela aparece em pesquisas que não especificam uma versão e saber que é possível no 4.0 pode ajudar alguém.
Jason Goemaat
Respostas:
162
var ints =newint[]{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 : a partir de (pelo menos) .NET 4.5,
var result =string.Join(",", ints.Select(x => x.ToString()).ToArray());
é equivalente a:
var result =string.Join(",", ints);
EDITAR :
Vejo que várias soluções anunciam o uso de StringBuilder. Alguém reclama que o método Join deve ter um argumento IEnumerable.
Vou desapontá-lo :) String.Join requer array por um único motivo - desempenho. O método de junção precisa saber o tamanho dos dados para pré-alocar efetivamente a quantidade necessária de memória.
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 separatorstring str =FastAllocateString(length);fixed(char* chRef =&str.m_firstChar)// note than we use direct memory access here{UnSafeCharBuffer buffer =newUnSafeCharBuffer(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 métodos sugeridos. Mas algo me diz que o Join vai ganhar :)
Esta é provavelmente a melhor aposta usando métodos de extensão .NET básicos, mas eu realmente gostaria que string.Join () aceitasse um IEnumerable <string> para evitar a conversão de ToArray ().
spoulson
Nada impede que alguém sobrecarregue string.Join para pegar um IEnumerable também. ;)
Robert P de
1
Esta é provavelmente a solução mais fácil, e não apenas a mais rápida.
Acho que há vários outros casos em que o uso das funções Convert.xxx é uma alternativa mais adequada a um lambda, embora em C # 3 o lambda possa ajudar na inferência de tipo.
Uma versão C # 3 bastante compacta que funciona com .NET 2.0 é esta:
Uma mistura das duas abordagens seria escrever um método de extensão em IEnumerable <T> que usasse um StringBuilder. Aqui está um exemplo, com diferentes sobrecargas dependendo se você deseja especificar a transformação ou apenas contar com ToString simples. 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;publicstaticclassExtensions{publicstaticstringJoinStrings<T>(thisIEnumerable<T> source,Func<T,string> projection,string separator){StringBuilder builder =newStringBuilder();bool first =true;foreach(T element in source){if(first){
first =false;}else{
builder.Append(separator);}
builder.Append(projection(element));}return builder.ToString();}publicstaticstringJoinStrings<T>(thisIEnumerable<T> source,string separator){returnJoinStrings(source, t => t.ToString(), separator);}}classTest{publicstaticvoidMain(){int[] x ={1,2,3,4,5,10,11};Console.WriteLine(x.JoinStrings(";"));Console.WriteLine(x.JoinStrings(i => i.ToString("X"),","));}}
Ótima solução! No entanto, você não precisa do parâmetro de projeção, pode apenas escrever x.Select (i => i.ToString ("X")). JoinStrings (";") que é mais idiomático.
JacquesB
Sim, pensei nisso depois. Ocasionalmente, é bom poder especificar tudo de uma vez, mas é definitivamente mais elegante dividir as operações :)
Temos que converter cada um dos itens em a Stringantes de podermos juntá-los, então faz sentido usar Selecte uma expressão lambda. Isso é equivalente a mapem alguns outros idiomas. Então, temos que converter a coleção de strings resultante em um array, porque String.Joinsó aceita um array de strings.
O ToArray()é um pouco feio eu acho. String.Joindeve realmente aceitar IEnumerable<String>, não há razão para restringi-lo apenas a arrays. Isso provavelmente ocorre porque Joiné anterior aos genéricos, quando os arrays eram o único tipo de coleção tipada disponível.
Edit: Quando postei isso, tive a impressão equivocada de que "StringBuilder.Append (valor int)" conseguiu anexar internamente a representação de string do valor inteiro sem criar um objeto de string. Isso está errado: inspecionar o método com o Reflector mostra que ele simplesmente anexa value.ToString ().
Portanto, a única diferença de desempenho potencial é que essa técnica evita a criação de uma matriz e libera as strings para coleta de lixo um pouco mais cedo. Na prática, isso não fará nenhuma diferença mensurável, então votei a favor dessa solução melhor .
Você mediu para ser mais rápido? String.Join usa um StringBuilder também.
JacquesB
Sim, mas primeiro você precisa converter tudo em um array, o que está longe de ser o ideal. Em particular, significa que você precisa ter todas as strings convertidas na memória ao mesmo tempo, antes de começar a construir a string resultante.
Jon Skeet
OTOH String.Join calcula previamente o tamanho do buffer StringBuilder para evitar o redimensionamento. Portanto, pode ser mais rápido mesmo que exija mais memória.
JacquesB
5
A questão é a "maneira mais fácil de convertê-los em uma única string onde os números são separados por um caractere".
A maneira mais fácil é:
int[] numbers =newint[]{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+, perdi o requisito do .NET 3.5 na primeira vez que li a pergunta.
É um método sobrecarregado: msdn.microsoft.com/en-us/library/dd988350 Acabei de copiar o código que escrevi em um novo aplicativo de console, adicionei um Console.WriteLine e este é o resultado: 2,3,6,7
WebMasterP
1
Acho que está disponível apenas em .net 4
Govind Malviya
Requer uma matriz de objeto (ou matriz de string), não uma matriz int. Irá dar um erro "a chamada é ambígua".
LarryBud
2
Concordo com a expressão lambda para legibilidade e manutenção, mas nem sempre será a melhor opção. A desvantagem de usar as abordagens IEnumerable / ToArray e StringBuilder é que eles precisam aumentar dinamicamente uma lista, seja de itens ou caracteres, pois não sabem quanto espaço será necessário para a string final.
Se o caso raro em que a velocidade é mais importante do que a concisão, o seguinte é mais eficiente.
int[] number =newint[]{1,2,3,4,5};string[] strings =newstring[number.Length];for(int i =0; i < number.Length; i++)
strings[i]= number[i].ToString();string result =string.Join(",", strings);
Obrigado, adicionei Substring(1)para consertar isso (era de memória).
vazio em
2
No .NET 4.0, string join tem uma sobrecarga para params object[], então é tão simples quanto:
int[] ids =newint[]{1,2,3};string.Join(",", ids);
exemplo
int[] ids =newint[]{1,2,3};System.Data.Common.DbCommand cmd =newSystem.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 pouco mais difícil, já que não existe essa sobrecarga. Portanto, você precisa de seu próprio método genérico:
publicstaticstringJoinArray<T>(string separator, T[] inputTypeArray){string strRetValue =null;System.Collections.Generic.List<string> ls =newSystem.Collections.Generic.List<string>();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 métodos de extensão:
publicstaticclassArrayEx{publicstaticstringJoinArray<T>(this T[] inputTypeArray,string separator){string strRetValue =null;System.Collections.Generic.List<string> ls =newSystem.Collections.Generic.List<string>();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;}}
Portanto, você pode usar o método de extensão JoinArray.
Você também pode usar esse método de extensão no .NET 2.0, se 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)]publicsealedclassExtensionAttribute:Attribute{}}
.NET 4.0
então, existem métodos que usam uma matriz de objetos e um IEnumerable para que você possa apenas fazerstring.join(",", number)
. Eu sei que a pergunta especifica .NET 3.5, então não respondi, mas ela aparece em pesquisas que não especificam uma versão e saber que é possível no 4.0 pode ajudar alguém.Respostas:
EDITAR : a partir de (pelo menos) .NET 4.5,
é equivalente a:
EDITAR :
Vejo que várias soluções anunciam o uso de StringBuilder. Alguém reclama que o método Join deve ter um argumento IEnumerable.
Vou desapontá-lo :) String.Join requer array por um único motivo - desempenho. O método de junção precisa saber o tamanho dos dados para pré-alocar efetivamente a quantidade necessária de memória.
Aqui está uma parte da implementação interna do método String.Join:
Estou com preguiça de comparar o desempenho dos métodos sugeridos. Mas algo me diz que o Join vai ganhar :)
fonte
using System.Linq;
É necessário.Embora o OP tenha especificado .NET 3.5, as pessoas que desejam fazer isso no .NET 2.0 com C # 2 podem fazer isso:
Acho que há vários outros casos em que o uso das funções Convert.xxx é uma alternativa mais adequada a um lambda, embora em C # 3 o lambda possa ajudar na inferência de tipo.
Uma versão C # 3 bastante compacta que funciona com .NET 2.0 é esta:
fonte
Uma mistura das duas abordagens seria escrever um método de extensão em IEnumerable <T> que usasse um StringBuilder. Aqui está um exemplo, com diferentes sobrecargas dependendo se você deseja especificar a transformação ou apenas contar com ToString simples. 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 :)
fonte
Temos que converter cada um dos itens em a
String
antes de podermos juntá-los, então faz sentido usarSelect
e uma expressão lambda. Isso é equivalente amap
em alguns outros idiomas. Então, temos que converter a coleção de strings resultante em um array, porqueString.Join
só aceita um array de strings.O
ToArray()
é um pouco feio eu acho.String.Join
deve realmente aceitarIEnumerable<String>
, não há razão para restringi-lo apenas a arrays. Isso provavelmente ocorre porqueJoin
é anterior aos genéricos, quando os arrays eram o único tipo de coleção tipada disponível.fonte
Se sua matriz de inteiros for grande, você obterá melhor desempenho usando um StringBuilder. Por exemplo:
Edit: Quando postei isso, tive a impressão equivocada de que "StringBuilder.Append (valor int)" conseguiu anexar internamente a representação de string do valor inteiro sem criar um objeto de string. Isso está errado: inspecionar o método com o Reflector mostra que ele simplesmente anexa value.ToString ().
Portanto, a única diferença de desempenho potencial é que essa técnica evita a criação de uma matriz e libera as strings para coleta de lixo um pouco mais cedo. Na prática, isso não fará nenhuma diferença mensurável, então votei a favor dessa solução melhor .
fonte
A questão é a "maneira mais fácil de convertê-los em uma única string onde os números são separados por um caractere".
A maneira mais fácil é:
EDIT: Isso só funciona no .NET 4.0+, perdi o requisito do .NET 3.5 na primeira vez que li a pergunta.
fonte
Concordo com a expressão lambda para legibilidade e manutenção, mas nem sempre será a melhor opção. A desvantagem de usar as abordagens IEnumerable / ToArray e StringBuilder é que eles precisam aumentar dinamicamente uma lista, seja de itens ou caracteres, pois não sabem quanto espaço será necessário para a string final.
Se o caso raro em que a velocidade é mais importante do que a concisão, o seguinte é mais eficiente.
fonte
Também achei que havia uma maneira mais simples. Não sabe sobre performance, alguém tem alguma ideia (teórica)?
fonte
Substring(1)
para consertar isso (era de memória).No .NET 4.0, string join tem uma sobrecarga para
params object[]
, então é tão simples quanto:exemplo
No .NET 2.0, é um pouco mais difícil, já que não existe essa sobrecarga. Portanto, você precisa de seu próprio método genérico:
No .NET 3.5, você pode usar métodos de extensão:
Portanto, você pode usar o método de extensão JoinArray.
Você também pode usar esse método de extensão no .NET 2.0, se adicionar o ExtensionAttribute ao seu código:
fonte
Você pode fazer
Verificação de saída
ToString delimitado por separador para matriz, lista, dicionário, IEnumerable genérico
fonte