2011-05-09 68 views
5

可以說我有一個字符串列表:兩個列表的補充?

A,B,C,d

然後串

的另一份名單

B,C,d

我想知道哪些要素在第一個列表中不在第二個列表中,所以結果將是A

我不知道要做到這一點的擴展方法的名稱是。我知道我可以使用concat,union和intersect進行類似的列表比較,但只是不知道要完成這個特定任務的名稱。

附錄,我對重複,因此,如果第一列表是:

A,A,A,B,C,d

和第二列表是

B,C ,d

我想

A,A,A

謝謝!

+1

使用集合,如果你用小列表進行幾次以上的操作。這不僅是更合適的方法,而且複雜性也要好上千倍。 – delnan 2011-05-09 15:57:57

+0

謝謝,這個問題涉及數千行 – sooprise 2011-05-09 16:06:35

回答

14

可以使用Except Extension Method來獲取列表不在第二列表中的所有元素:

var result = list1.Except(list2); 
+0

這個返回重複嗎? – sooprise 2011-05-09 16:04:22

+0

我想複製 – sooprise 2011-05-09 16:07:49

3
var result = list1.Where(i => !list2.Contains(i)); 
+0

這裏沒有內置的擴展方法嗎? – sooprise 2011-05-09 15:57:46

+0

+1這正是我所要做的。 – 2011-05-09 15:58:55

+0

您可以構建一個擴展方法來完成此操作。 – 2011-05-09 15:59:12

4

的「除」,在BCL方法移除所有重複,這是不是有什麼你要。

如果問題中的列表很大,那麼爲了有效地做到這一點,您可能需要浪費內存以換取時間節省。例如:

// yield all members of "sequence" omitting those in "except" 
static IEnumerable<string> Filter(
    this IEnumerable<string> sequence, 
    IEnumerable<string> except) 
{ 
    var set = new HashSet<string>(except); // Burn memory to save time 
    return from item in sequence 
      where !set.Contains(item) 
      select item; 
} 

這樣,每次測試項目時都可以快速查找。

var sequence = new List<string>() { A, B, A, C, D }; 
var except = new List<string>() { B, C }; 
var result = sequence.Filter(except).ToList(); 
+1

請注意,如果第一個列表是A,A,B和第二個列表A,則這將返回B. – Brian 2011-05-09 20:39:59

0

如果你重複的定義包括兩個列表要高效地計算補調用它,那麼你就需要使用不同的數據結構:一個袋子。一個包是一個允許重複的集合。

下面是一個名爲BagDifference的擴展方法,它有效地解釋了任一列表中的重複項以及由Eric的答案啓發的示例程序。

public class Bag<T> : Dictionary<T, int> 
{ 
    public Bag(IEnumerable<T> sequence) 
    { 
     foreach (var item in sequence) 
     { 
      if (!ContainsKey(item)) this[item] = 0; 
      ++this[item]; 
     } 
    } 
} 

public static class EnumerableExtensions 
{ 
    public static IEnumerable<T> BagDifference<T>(this IEnumerable<T> sequence1, IEnumerable<T> sequence2) 
    { 
     var bag1 = new Bag<T>(sequence1); 
     var bag2 = new Bag<T>(sequence2); 
     foreach (var item in bag1.Keys) 
     { 
      var count1 = bag1[item]; 
      var count2 = bag2.ContainsKey(item) ? bag2[item] : 0; 
      var difference = Math.Max(0, count1 - count2); 
      for (int i = 0; i < difference; i++) 
       yield return item; 
     } 
    } 
} 

class Program 
{ 

    static void Main(string[] args) 
    { 
     var sequence = new List<string>() { "A", "B", "A", "C", "D" }; 
     var except = new List<string>() { "A", "B", "C", "C" }; 
     var difference = sequence.BagDifference(except).ToList(); 
    } 
}