2010-05-12 75 views
11

如果我有:轉換陣列連接字符串

List<Car> 

其中汽車:

public class Car 
{ 
     public int Year; 
     public string Name; 
} 

,我想利用這個陣列,並創建一個連接字符串「」

所以它會返回:

"Toyota, Ford, Chevy" 

我可以手動像這樣做:

private static string CreateConcatenatedList(List<Car> parts_) 
    { 
     StringBuilder b = new StringBuilder(); 
     foreach (Car bp in parts_) 
     { 
      b.Append(bp.Name + ", "); 
     } 
     b.Remove(b.Length - 2, 2); 
     return b.ToString(); 
    } 

,但我認爲有可能是一個更優雅的方式

+0

對於大約一百萬個解決方案,其中很多都是錯誤的,對於相關問題,請參閱http://blogs.msdn.com/ericlippert/archive/2009/04/15/comma-quibbling.aspx – 2010-05-12 14:07:12

回答

10
List<Car> cars = //whatever; 
string concat = String.Join(",", cars.Select(c => c.Name).ToArray()); 

編輯:您還可以使用聚合如果你擔心創建中間陣列:

string concat = cars.Select(c => c.Name).Aggregate(new StringBuilder(), (sb, current) => 
{ 
    return sb.Length == 0 ? sb.Append(current) : sb.AppendFormat(",{0}", current); 
}).ToString(); 
+0

比我的解決方案還是更快? – leora 2010-05-12 12:33:19

+0

@oo - 它創建了一個效率稍低的中間數組,儘管除非列表中有很多元素,否則您可能不會注意到。你可以使用Aggregate來避免這種情況。 – Lee 2010-05-12 12:44:27

+2

.NET 4.0包含一個string.join重載接受IEnumberable:http://msdn.microsoft.com/en-us/library/dd783876.aspx – Dykam 2010-05-12 13:02:47

5
List<Car> cars = .... 
var result = string.Join(",", cars.Select(car => car.Name).ToArray()); 
+1

的註釋。在.NET 4.0中,您不需要'.ToArray()',因爲'String.Join'現在具有'IEnumerable '的超載::http://msdn.microsoft.com/en-us/library/dd783876 .aspx – 2010-05-12 12:36:20

1

我認爲那是你真正想要的是:

寫在你的問題

"Toyota", "Ford", "Chevy" 

"Toyota, Ford, Chevy" 

不能及的。這樣就可以實現像這樣:

var cars = new List<Car>(); 

var delimitedString = string.Join(", ", cars.Select(c => c.Name).ToArray()); 
+0

你是對的。我已經更新了問題 – leora 2010-05-12 12:38:23

1
ArrayList<Car> cars = ... 
string finalValue = string.Join(",", cars.Select(c => c.Name).ToArray()); 
+0

哈哈哈哈!全部都一樣 ;) – 2010-05-12 12:33:37

1

我寫了下面extention方法這種類型的案件。它使用一個字符串生成器和Aggregate,而不是string.Join和一個數組,以提高性能。

public static string Concatenate(
    this IEnumerable<string> collection, 
    string separator) 
{ 
    return collection 
     .Skip(1) 
     .Aggregate(
      new StringBuilder().Append(collection.First()), 
      (b, s) => b.Append(separator).Append(s)) 
     .ToString(); 
} 

然後在你的情況下,它只是

cars.Select(c=>Name).Concatenate(", "); 
6

因爲你在閱讀到答案評論詢問是否是快/慢或只是更少的代碼。我嘗試了一下,並寫了一個小的汽車類:

private static Random random = new Random((int)DateTime.Now.Ticks); 
private static string RandomString(int min, int max) 
{ 
    string str = ""; 
    int size = random.Next(min, max + 1); 
    for (int i = 0; i < size; i++) 
     str += Convert.ToChar(Convert.ToInt32(
         Math.Floor(26 * random.NextDouble() + 65))); 
    return str; 
} 

public static void MeassureTicks(int numberCars, int minLength, int maxLength) 
{ 
    // Generate random list 
    List<Car> cars = Enumerable.Range(0, numberCars) 
        .Select(x => new Car(RandomString(
          minLength, maxLength))).ToList(); 

    Stopwatch sw1 = new Stopwatch(), sw2 = new Stopwatch(), 
       sw3 = new Stopwatch(), sw4 = new Stopwatch(); 

    sw1.Start(); 
    string concat1 = CreateConcatenatedList(cars); 
    sw1.Stop(); 
    sw2.Start(); 
    string concat2 = String.Join(",", cars.Select(c => c.Name).ToArray()); 
    sw2.Stop(); 
    sw3.Start(); 
    if (numberCars <= 5000) 
    { 
     string concat3 = cars.Select(c => c.Name).Aggregate("", 
       (str, current) => 
       { 
        return str.Length == 0 ? str = current : 
          str += "," + current; 
       }).ToString(); 
    } 
    sw3.Stop(); 
    sw4.Start(); 
    string concat4 = cars.Select(c => c.Name).Aggregate(
      new StringBuilder(), (sb, current) => 
      { 
       return sb.Length == 0 ? sb.Append(current) : 
         sb.AppendFormat(",{0}", current); 
      }).ToString(); 
    sw4.Stop(); 

    Console.WriteLine(string.Format("{0} car strings joined:\n" + 
       "\tYour method:     {1} ticks\n" + 
       "\tLinq+String.Join:    {2} ticks\n" + 
       "\tLinq+Aggregate+String.Concat: {3} ticks\n" + 
       "\tLinq+Aggregate+StringBuilder: {4} ticks\n", 
       cars.Count, sw1.ElapsedTicks, sw2.ElapsedTicks, 
       numberCars <= 5000 ? sw3.ElapsedTicks.ToString() : "-", 
       sw4.ElapsedTicks)); 

更新:

public class Car 
{ 
    public string Name { get; set; } 
    public Car(string name) { Name = name; } 
} 

長度爲5-10的隨機生成的字符串測試它 我現在想這兩種方法是也在使用聚合。

輸出是在我的電腦的一些不同的汽車數量:

5 car strings joined: 
     Your method:     14 ticks 
     Linq+String.Join:    20 ticks 
     Linq+Aggregate+String.Concat: 11 ticks 
     Linq+Aggregate+StringBuilder: 15 ticks 

50 car strings joined: 
     Your method:     50 ticks 
     Linq+String.Join:    45 ticks 
     Linq+Aggregate+String.Concat: 70 ticks 
     Linq+Aggregate+StringBuilder: 73 ticks 

500 car strings joined: 
     Your method:     355 ticks 
     Linq+String.Join:    348 ticks 
     Linq+Aggregate+String.Concat: 5365 ticks 
     Linq+Aggregate+StringBuilder: 619 ticks 

5000 car strings joined: 
     Your method:     3584 ticks 
     Linq+String.Join:    3357 ticks 
     Linq+Aggregate+String.Concat: 379635 ticks 
     Linq+Aggregate+StringBuilder: 6078 ticks 

50000 car strings joined: 
     Your method:     33705 ticks 
     Linq+String.Join:    34082 ticks 
     Linq+Aggregate+String.Concat: - ticks 
     Linq+Aggregate+StringBuilder: 92839 ticks 

500000 car strings joined: 
     Your method:     508439 ticks 
     Linq+String.Join:    376339 ticks 
     Linq+Aggregate+String.Concat: - ticks 
     Linq+Aggregate+StringBuilder: 616048 ticks 

LINQ的+ String.Join方法確實有點快更少的代碼。與StringBuilter一起縮放非常好(不像字符串連接),但速度稍慢。因此,要麼使用你的方法,要麼Linq + String.Join,這是一個很好的線上,也容易閱讀。