배열이 다른 배열의 하위 집합인지 확인하십시오
문제
그 목록이 다른 사람의 하위 집합인지 확인하는 방법에 대한 아이디어가 있습니까?
구체적으로, 나는 가지고 있습니다
List<double> t1 = new List<double> { 1, 3, 5 };
List<double> t2 = new List<double> { 1, 5 };
LINQ를 사용하여 T2가 T1의 서브 세트인지 확인하는 방법은 무엇입니까?
해결책
bool isSubset = !t2.Except(t1).Any();
다른 팁
세트로 작업하는 경우 목록 대신 해시 세트를 사용하십시오. 그런 다음 간단히 사용할 수 있습니다 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);
@Cameron의 확장 방법으로서의 솔루션 :
public static bool IsSubsetOf<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
return !a.Except(b).Any();
}
용법:
bool isSubset = t2.IsSubsetOf(t1);
(이것은 비슷하지만 @Michael의 블로그에 게시 된 것과는 다릅니다)
이것은 여기에 게시 된 다른 솔루션, 특히 최고 솔루션보다 훨씬 더 효율적인 솔루션입니다.
bool isSubset = t2.All(elem => t1.Contains(elem));
T1이 아닌 T2에서 단일 요소를 찾을 수 있다면 T2가 T1의 서브 세트가 아니라는 것을 알고 있습니다. 이 방법의 장점은 .excrep 또는 .intersect를 사용하는 솔루션과 달리 추가 공간을 할당하지 않고 모든 장소에서 수행된다는 것입니다. 또한,이 솔루션은 하위 집합 조건을 위반하는 단일 요소를 찾는 즉시 파손될 수 있지만 다른 솔루션은 계속 검색합니다. 아래는 최적의 긴 형태의 솔루션으로, 위의 속기 솔루션보다 테스트에서 약간 빠릅니다.
bool isSubset = true;
foreach (var element in t2) {
if (!t1.Contains(element)) {
isSubset = false;
break;
}
}
나는 모든 솔루션에 대한 초보적인 성능 분석을 수행했으며 결과는 과감합니다. 이 두 솔루션은 .excrect () 및 .intersect () 솔루션보다 약 100 배 빠르며 추가 메모리를 사용하지 않습니다.
@Cameron과 @Neil의 답변을 바탕으로 열거 가능한 클래스와 동일한 용어를 사용하는 확장 방법을 썼습니다.
/// <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();
}
여기서 우리는 어린이 목록에 요소가 있는지 확인합니다 (즉
t2
) 부모 목록에 포함되지 않습니다 (예 :t1
). 그러한 존재가 없다면 목록은 다른 사람의 하위 집합입니다.
예 :
bool isSubset = !(t2.Any(x => !t1.Contains(x)));
이 시도
static bool IsSubSet<A>(A[] set, A[] toCheck) {
return set.Length == (toCheck.Intersect(set)).Count();
}
여기서 아이디어는 교차가 두 배열에있는 값 만 반환한다는 것입니다. 이 시점에서 결과 세트의 길이가 원래 세트와 동일하다면 "Set"의 모든 요소는 "Check"에 있으므로 "세트"는 "Tocheck"의 하위 집합입니다.
참고 : "세트"에 복제가있는 경우 내 솔루션이 작동하지 않습니다. 나는 다른 사람들의 투표를 훔치고 싶지 않기 때문에 그것을 바꾸지 않습니다.
힌트 : 나는 카메론의 대답에 투표했다.