2012-03-05 57 views
2

我有喜歡C#:如何使用Linq/Lambda比較兩個集合(System.Collection.Generic.List <T>)?

List<String> l_lstOne = new List<String> { "100", "1X0", "X11", "XXX" }, 
    l_lstTwo = new List<String> { "000", "110", "100", "000" }; 

String兩個集合,我需要比較兩個列表和使第二列表像

{ "000", "1X0", "X00", "XXX" } 

注: 兩個列表將包含相同的numbe的元素和每個元素的長度將是相同的。

時比較結果爲像

  1. 如果l_lstOne第m元件具有在第n個位置上的「X」,在l_lstTwo第m的第n個位置應當由「X」所取代。

l_lstOne   l_lstTwo  Output 

     100     000    000 
     1X0     110    1X0 
     X11     100    X00 

因此,要解決這個我用嵌套的for循環,這裏是我的源代碼,

for (int l_nIndex = 0; l_nIndex < l_lstTwo.Count; l_nIndex++) 
     { 
      String l_strX = String.Empty; 

      for (int l_nInnerIndex = 0; l_nInnerIndex < l_lstTwo[l_nInnerIndex].Length; l_nInnerIndex++) 
      { 
       l_strX += l_lstOne[l_nIndex][l_nInnerIndex] == 'X' ? 'X' : l_lstTwo[l_nIndex][l_nInnerIndex]; 
      } 
      l_lstTwo[l_nIndex] = l_strX; 
     } 

此代碼工作正常,但事情是,其花費更多的時間來執行,即幾乎600毫秒來處理200000個元素並且每個長度爲16.

此外我需要一個Linq或Lambda方法來解決這個問題。所以請幫助我做到這一點。提前致謝。

+0

@Robert哈維:謝謝你......但我不明白你的'Sort'是什麼意思。 – 2012-03-05 06:20:23

回答

5

LINQ不會幫你在這裏; LINQ並不意味着要修改集合。

通過構建char[]而不是string,可以使您的代碼快得多;現在,由於+=,您正在構建320萬個string對象。

相反,你可以寫

char[] l_strX = new char[l_lstTwo[l_nInnerIndex].Length]; 

for (int l_nInnerIndex = 0; l_nInnerIndex < l_lstTwo[l_nInnerIndex].Length; l_nInnerIndex++) 
{ 
    l_strX[l_nInnerIndex] = l_lstOne[l_nIndex][l_nInnerIndex] == 'X' ? 'X' : l_lstTwo[l_nIndex][l_nInnerIndex]; 
} 
l_lstTwo[l_nIndex] = new string(l_strX); 
+0

謝謝......它將處理時間從600毫秒減少到300毫秒。 – 2012-03-05 06:23:32

2

MH,如果我理解正確的l_lstOne行爲的話,如l_lstTwo的話口罩,其中掩碼是透明的,除非它是一個X。這個怎麼樣:

l_lstOne.Zip(l_lstTwo, 
    (w1, w2) => new String(w1.Zip(w2, (c1, c2) => c1 == 'X' ? c1 : c2).ToArray()))) 

Zip可從.NET 4上,結合兩個列表的像拉鍊元素的Linq extension method。外部zip基本上創建了單詞對來迭代,第二個創建了一個掩碼(從第二個字中取出所有字符,除非字在該位置有一個X)。

另請注意,這會創建一個新的字符串序列,而不是替換l_lstTwo中的字符串 - 這就是Linq做事的方式。

+0

謝謝。我正在使用.Net Framework 3.5。那麼是否有任何替代'Zip' – 2012-03-05 06:35:47

+2

@PramodhTS:你可以找到一個實現,如鏈接提供的對這個問題的答案:http://stackoverflow.com/questions/2811822/does-linq-net3-5- support-a-zip-method – ChrisWue 2012-03-05 06:43:29

2

你可以用下面的語句做在.net 3.5

IEnumerable <String> result = 
     Enumerable.Range(0, l_lstOne.Count) 
      .Select(i => Enumerable.Range(0, l_lstOne[i].Length) 
       .Aggregate(string.Empty, (innerResult, x) => innerResult += l_lstOne[i][x] == 'X' ? 'X' : l_lstTwo[i][x])); 
+0

如果在聚集中使用StringBuilder而不是字符串連接會使性能出現差異(避免創建大量臨時字符串),那麼測量會很有趣 – ChrisWue 2012-03-05 07:15:28

+0

@ChrisWue:區別。看到我的答案下面的評論。 – SLaks 2012-03-05 18:00:15