답변:
bool isSubset = !t2.Except(t1).Any();
세트로 작업하는 경우 List 대신 HashSet을 사용하십시오. 그런 다음 간단히 IsSubsetOf () 를 사용할 수 있습니다
HashSet<double> t1 = new HashSet<double>{1,3,5};
HashSet<double> t2 = new HashSet<double>{1,5};
bool isSubset = t2.IsSubsetOf(t1);
LINQ를 사용하지 않아서 죄송합니다. :-(
목록을 사용해야하는 경우 @Jared의 솔루션은 존재하는 반복되는 요소를 제거해야한다는 경고와 함께 작동합니다.
당신이 경우 단위 테스트 당신은 또한 활용할 수 CollectionAssert.IsSubsetOf의 방법 :
CollectionAssert.IsSubsetOf(subset, superset);
위의 경우 이는 다음을 의미합니다.
CollectionAssert.IsSubsetOf(t2, t1);
이것은 여기에 게시 된 다른 솔루션, 특히 최고의 솔루션보다 훨씬 효율적인 솔루션입니다.
bool isSubset = t2.All(elem => t1.Contains(elem));
t2에서 t1에없는 단일 요소를 찾을 수 있으면 t2가 t1의 하위 집합이 아님을 알 수 있습니다. 이 방법의 장점은 .Except 또는 .Intersect를 사용하는 솔루션과 달리 추가 공간을 할당하지 않고 모든 위치에서 수행된다는 것입니다. 또한이 솔루션은 하위 집합 조건을 위반하는 단일 요소를 찾은 후 다른 요소는 계속 검색하면서 중단 될 수 있습니다. 아래는 최적의 긴 형태의 솔루션이며 위의 속기 솔루션보다 테스트에서 약간 빠릅니다.
bool isSubset = true;
foreach (var element in t2) {
if (!t1.Contains(element)) {
isSubset = false;
break;
}
}
모든 솔루션에 대한 기초적인 성능 분석을 수행했으며 그 결과는 극적입니다. 이 두 솔루션은 .Except () 및 .Intersect () 솔루션보다 약 100 배 빠르며 추가 메모리를 사용하지 않습니다.
!t2.Except(t1).Any()일을하는 것입니다. Linq는 계속해서 노력하고 있습니다. 하나 이상의 요소가 있는지 Any()묻습니다 IEnumerable. 이 시나리오에서는 에없는 t2.Except(t1)첫 번째 요소 만 방출합니다 . 의 첫 번째 요소는 경우 에없는 의 모든 요소가있는 경우는, 가장 빠른 완료 에 가 가장 긴 실행됩니다. t2t1t2t1t2t1
t1={1,2,3,...9999}그리고 t2={9999,9998,99997...9000}당신은 다음과 같은 측정을 얻는다는 것을 알았습니다 !t2.Except(t1).Any(): 1ms -> t2.All(e => t1.Contains(e)): 702ms. 그리고 범위가 클수록 악화됩니다.
t2.Except (t1)를 반환 IEnumerable하지 않습니다 Collection. 예를 들어 ToArray ()또는 내부를 침입하지 않고 ToList ()사용 하거나 완전히 반복하는 경우 가능한 모든 항목을 방출합니다 foreach. linq 지연된 실행 을 검색하여 해당 개념에 대해 자세히 알아보십시오.
t2={1,2,3,4,5,6,7,8} t1={2,4,6,8} t2.Except(t1)=> t2의 첫 번째 요소 = 1 => 1 과 t1의 차이 는 1입니다 ({2,4,6,8}에 대해 확인) => Except()첫 번째 요소 방출 1 => Any()요소 가져 오기 => Any()t2에서 요소를 더 이상 검사하지 않는 true => 결과.
@Cameron 및 @Neil의 답변을 바탕으로 Enumerable 클래스와 동일한 용어를 사용하는 확장 메서드를 작성했습니다.
/// <summary>
/// Determines whether a sequence contains the specified elements by using the default equality comparer.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">A sequence in which to locate the values.</param>
/// <param name="values">The values to locate in the sequence.</param>
/// <returns>true if the source sequence contains elements that have the specified values; otherwise, false.</returns>
public static bool ContainsAll<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> values)
{
return !values.Except(source).Any();
}
이 시도
static bool IsSubSet<A>(A[] set, A[] toCheck) {
return set.Length == (toCheck.Intersect(set)).Count();
}
여기서 아이디어는 Intersect가 두 배열에있는 값만 반환한다는 것입니다. 이 시점에서 결과 집합의 길이가 원래 집합과 동일하면 "set"의 모든 요소도 "check"에 있고 "set"은 "toCheck"의 하위 집합입니다.
참고 : "set"에 중복이 있으면 내 솔루션이 작동하지 않습니다. 다른 사람들의 투표를 훔치고 싶지 않기 때문에 변경하지 않습니다.
힌트 : Cameron의 답변에 투표했습니다.