List <int> öğesini virgülle ayrılmış dizeye dönüştürme


116

Bir Listeyi virgülle ayrılmış dizgeye dönüştürmenin bir yolu var mı?

Dönüp inşa edebileceğimi biliyorum, ama bir şekilde bazılarınız bunu yapmanın daha havalı bir yolunu?

Bu tür 'hileleri' gerçekten öğrenmek istiyorum, bu yüzden lütfen kullandığınız yöntemle ilgili belgeleri açıklayın veya bunlara bağlantı verin.

Yanıtlar:


189
List<int> list = ...;
string.Join(",", list.Select(n => n.ToString()).ToArray())

7
Eleman başına bir dizge ayırdığı için akıllıca ama yavaş ve şişirilmiş. Bir StringBuilder kullanmak çok daha verimli olacaktır.
Steven Sudit

3
Çevrimiçi gördüğüm kadarıyla (hızlı arama) String.Join, StringBuilder kullanmaktan daha hızlıdır.
Yuriy Faktorovich


6
Steven'ın String.Join yerine n.ToString () kısmından bahsettiğini düşünüyorum.
Larsenal

9
Larsenal: ancak StringBuilder.Append (Int32) dahili olarak tamsayı üzerinde ToString'i çağırır. StringBuilder sihirli bir şekilde her öğe için bir dizge ayırma maliyetinden kaçınmaz; sadece güzelce gözden kaybolur.
itowlson

115

Basit çözüm

List<int> list = new List<int>() {1,2,3};
string.Join<int>(",", list)

Onu şimdi kodumda kullandım, funtastic çalışıyordum.


1
Teşekkür! bu güzel bir yaklaşım
Irfan Ashraf

2
Bu, kabul edilen cevaptan daha iyi bir yaklaşımdır. Bu yaklaşımla Linq'i içe aktarmanız gerekmez ve bu daha hızlıdır.
JoKeRxbLaCk

Güzel! String'i hiç bilmiyordum.Join genel aşırı yüklere sahiptir. Teşekkürler.
mrmashal

10
List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(String.Join(",", list.Select(i => i.ToString()).ToArray()));

NET 4'ü kullanamıyorsanız harika
Greg Woods

6

Bu sorunun biraz daha karmaşık bir versiyonuna yaklaşık bir gazilyon çözüm için - çoğu yavaş, hatalı ya da derlenmiyor - bu konuyla ilgili makaleme yapılan yorumlara bakın:

http://blogs.msdn.com/ericlippert/archive/2009/04/15/comma-quibbling.aspx

ve StackOverflow yorumu:

Eric Lippert'in meydan okuması "virgül-kelime oyunu", en iyi cevap?


Bağlantı için teşekkürler. Bu dizi birleştirme problemi beklediğimden daha karmaşık ve daha eğitici bir hal aldı!
Steven Sudit

4

Ekstra serinlik için bunu IEnumerable <T> üzerinde bir uzantı yöntemi yapardım, böylece herhangi bir IEnumerable üzerinde çalışır:

public static class IEnumerableExtensions {
  public static string BuildString<T>(this IEnumerable<T> self, string delim = ",") {
    return string.Join(delim, self)        
  }
}

Aşağıdaki gibi kullanın:

List<int> list = new List<int> { 1, 2, 3 };
Console.WriteLine(list.BuildString(", "));

Olası iki optimizasyon: 1) Her öğeden sonra sınırlayıcıyı ekleyin, ardından döngü bittikten sonra fazladan olanı kaldırın. 2) StringBuilder için bir kapasite belirtin.
Steven Sudit

1
Reflektörü kazarsanız, Join'in arabellek boyutunu önceden hesaplamak için uzunlukları topladığı ve ayrıca döngünün dışına ilk dizgiyi ekleyerek ve ardından döngünün içinde, sınırlayıcıyı koşulsuz olarak sonraki dize. Bazı güvensiz / dahili hilelerle birleştirildiğinde, çok hızlı olmalıdır.
Steven Sudit

@Steven: tavsiyene uy.
cdiggins

1
Uzantınızdaki sınırlayıcıyı sabit kodluyorsunuz ve bir sınırlayıcı için aktarılan değeri yok sayıyorsunuz ve noktalı virgülü kaçırdınız. O olmalıreturn string.Join(delim, self);
Andrew

1

Oldukça hızlı görünüyor.

IList<int> listItem = Enumerable.Range(0, 100000).ToList();
var result = listItem.Aggregate<int, StringBuilder, string>(new StringBuilder(), (strBuild, intVal) => { strBuild.Append(intVal); strBuild.Append(","); return strBuild; }, (strBuild) => strBuild.ToString(0, strBuild.Length - 1));

1

"Akıllı" girişim:

        List<int> list = new List<int> { 1, 2, 3 };
        StringBuilder sb = new StringBuilder();
        var y = list.Skip(1).Aggregate(sb.Append(x.ToString()),
                    (sb1, x) =>  sb1.AppendFormat(",{0}",x));

        // A lot of mess to remove initial comma
        Console.WriteLine(y.ToString().Substring(1,y.Length - 1));

Virgülü koşullu olarak nasıl ekleyeceğimi henüz çözemedim.


1
Lütfen Selectlambdada yan etkilerle yazmayın . Bu durumda kullanmıyorsun bile y, yani senin Selectaslında sadece bir foreach- bu yüzden böyle yaz.
Pavel Minaev

Bunu iyi bir çözüm olarak önermiyordum. OP, foreach'ten daha ilginç bir şey istedi.
Larsenal

Evet ama kötüye Selectolarak foreach"ilginç" Geçmiş ve, iyi, "istismar" girer. Daha ilginç bir yaklaşım burada kullanmak olacaktır Enumerable.Aggregateile StringBuilderbu deneyin - bir tohum değeri olarak.
Pavel Minaev

İyi bir fikir. Dışarı çıkmalıyım, ama bunu biraz deneyebilirim.
Larsenal

0

System.Linq kitaplığını kullanabilirsiniz; Daha etkilidir:

using System.Linq;
string str =string.Join(",", MyList.Select(x => x.NombreAtributo));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.