2009-04-30 6 views
15

Voglio ottenere la differenza tra due serie di pollici in C#. Dato s1 e s2 voglio restituire quegli int che sono in s1 e non in s2. Posso fare qualcosa come:C'è un modo per ottenere la differenza tra due serie di oggetti in C#

List<int> s1 = new List<int>(); 
    List<int> s2 = new List<int>(); 

    foreach (int i in s1) 
    { 
     if (s1.Contains(i)) 
     { 
      // 
     } 
     else 
     { 
      // 
     } 
    } 

Ma mi stavo chiedendo se qualcuno può indicare qualcosa di più pulito. Mi piacerebbe fare qualcosa come

List<int> omitted = s1.Difference(s2); 

Non so se c'è un metodo esistente o un LINQ costrutto che chiunque potrebbe essere in grado di sottolineare? Grazie.

risposta

18

Penso che tu voglia HashSet.Except. Cioè, piuttosto che usare gli elenchi, utilizzare HashSet e quindi l'operazione è disponibile. Questo è un tipo migliore se quello che stai rappresentando è davvero un "set" in ogni caso. (Se si dispone già di una lista, si può semplicemente creare una 'nuova HashSet' fuori di esso.)

+0

grazie fantastico. Tranne() è il metodo che stavo cercando e prendo il tuo consiglio su HashSets. – SiC

+0

Tranne che una funzione di estensione, no? – leppie

+0

Esiste un metodo di estensione Enumerable.Except for all IEnumerables. Ma HashSet ha un metodo Tranne specificamente per HashSet. – Brian

1
 
from x in s1 
where ! s2.contains(x) 
select x 
2
List<int> s1 = new List<int>(); 
List<int> s2 = new List<int>(); 

return sl.FindAll(i => !s2.Contains(i)) 
20
IEnumerable<T> a, b; 

var added = a.Except(b); 
var removed = b.Except(a); 
+1

Si noti che questo utilizza Enumerable.Except, quindi è necessario utilizzare System.Linq. http://msdn.microsoft.com/en-us/library/bb300779.aspx – Brian

+0

È un problema? :) – leppie

+1

Problema? No, volevo solo aiutare qualcuno che potrebbe tagliare e incollare questo codice e scoprire che non viene compilato. – Brian

0

Qui ci sono due metodi di estensione che potrebbero venire utile quando è necessario trovare non ordinata differenze tra due IEnumerable (è più o meno la stessa data dal wrapper leppie nei metodi di estensione):

public class EnumerableDifferences<T> 
{ 
    public IEnumerable<T> Added { get; } 
    public IEnumerable<T> Removed { get; } 

    public EnumerableDifferences(IEnumerable<T> added, IEnumerable<T> removed) 
    { 
     Added = added; 
     Removed = removed; 
    } 
} 

public static class EnumerableExtensions 
{ 
    public static HashSet<TSource> ToHashSet<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer) 
    { 
     return new HashSet<TSource>(source, comparer); 
    } 

    public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer = null) 
    { 
     return first 
      .ExceptBy(keySelector, second.Select(keySelector), keyComparer); 
    } 

    public static IEnumerable<TSource> ExceptBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEnumerable<TKey> keys, IEqualityComparer<TKey> keyComparer = null) 
    { 
     var secondKeys = keys.ToHashSet(keyComparer); 

     foreach (var firstItem in source) 
     { 
      var firstItemKey = keySelector(firstItem); 

      if (!secondKeys.Contains(firstItemKey)) 
      { 
       yield return firstItem; 
      } 
     } 
    } 

    public static EnumerableDifferences<TSource> DifferencesBy<TSource, TKey>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer = null) 
    { 
     keyComparer = keyComparer ?? EqualityComparer<TKey>.Default; 

     var removed = first.ExceptBy(second, keySelector, keyComparer); 
     var added = second.ExceptBy(first, keySelector, keyComparer); 

     var result = new EnumerableDifferences<TSource>(added, removed); 

     return result; 
    } 

    public static EnumerableDifferences<TSource> Differences<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer = null) 
    { 
     return first 
      .DifferencesBy(second, x => x, comparer); 
    } 
} 

public static class Program 
{ 
    public static void Main(params string[] args) 
    { 
     var l1 = new[] { 'a', 'b', 'c' }; 
     var l2 = new[] { 'a', 'd', 'c' }; 

     var result = l1.Differences(l2); 

     Console.ReadKey(); 
    } 
} 
Problemi correlati