을이 :
var newData = destination.Except(data.Select(x => f(x)));
당신은 '에 포함 된 동일한 유형의 데이터를'프로젝트가 대상 ',하지만 아래의 코드는이 제한을 제거 할 수 사용은 :
//Here is how you can compare two different sets.
class A { public string Bar { get; set; } }
class B { public string Foo { get; set; } }
IEnumerable<A> setOfA = new A[] { /*...*/ };
IEnumerable<B> setOfB = new B[] { /*...*/ };
var subSetOfA1 = setOfA.Except(setOfB, a => a.Bar, b => b.Foo);
//alternatively you can do it with a custom EqualityComparer, if your not case sensitive for instance.
var subSetOfA2 = setOfA.Except(setOfB, a => a.Bar, b => b.Foo, StringComparer.OrdinalIgnoreCase);
//Here is the extension class definition allowing you to use the code above
public static class IEnumerableExtension
{
public static IEnumerable<TFirst> Except<TFirst, TSecond, TCompared>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TCompared> firstSelect,
Func<TSecond, TCompared> secondSelect)
{
return Except(first, second, firstSelect, secondSelect, EqualityComparer<TCompared>.Default);
}
public static IEnumerable<TFirst> Except<TFirst, TSecond, TCompared>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TCompared> firstSelect,
Func<TSecond, TCompared> secondSelect,
IEqualityComparer<TCompared> comparer)
{
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
return ExceptIterator<TFirst, TSecond, TCompared>(first, second, firstSelect, secondSelect, comparer);
}
private static IEnumerable<TFirst> ExceptIterator<TFirst, TSecond, TCompared>(
IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TCompared> firstSelect,
Func<TSecond, TCompared> secondSelect,
IEqualityComparer<TCompared> comparer)
{
HashSet<TCompared> set = new HashSet<TCompared>(second.Select(secondSelect), comparer);
foreach (TFirst tSource1 in first)
if (set.Add(firstSelect(tSource1)))
yield return tSource1;
}
}
일부는 그 인해 HashSet의 사용에 메모리 비효율적 주장 할 수 있습니다. 그러나 실제로 프레임 워크의 Enumerable.Except 메서드는 'Set'이라는 비슷한 내부 클래스를 사용하여 동일한 작업을 수행합니다 (디 컴파일 링을 통해 살펴 보았습니다).
낡은'for' 루프가 좋지는 않았지만, 그는 한때 유용했지만, 아쉽게도 단호한 사람을 행복하게 만들지 않았습니다. – Marc
@Marc : 당신이 표현하고있는 정서에 동의하지 않습니다. 메커니즘에 대해 걱정하지 않고 의도를보다 명확하게 표현하는 코드를 작성하는 방법이 있습니다. 'for'는 메커니즘을 표현하고 의도를 모호하게 만듭니다. LINQ 기반의 단 하나의 라이너는 종종 (항상 그래야하는 것은 아니지만) 자주 비방하고 의도를 표현하고 메커니즘을 숨 깁니다. 이는 이해하기 쉽고 유지 보수가 쉬운 코드로 이어집니다. – jason
@ Jason, 내가 경박 해지는 동안, 당신과 같은 투사에 던지는 모든 기능은 의도의 가정만을 제공합니다. – Marc