답변:
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)
첫 번째 요소 만 방출합니다 . 의 첫 번째 요소는 경우 에없는 의 모든 요소가있는 경우는, 가장 빠른 완료 에 가 가장 긴 실행됩니다. t2
t1
t2
t1
t2
t1
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의 답변에 투표했습니다.