문제

그 목록이 다른 사람의 하위 집합인지 확인하는 방법에 대한 아이디어가 있습니까?

구체적으로, 나는 가지고 있습니다

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"의 하위 집합입니다.

참고 : "세트"에 복제가있는 경우 내 솔루션이 작동하지 않습니다. 나는 다른 사람들의 투표를 훔치고 싶지 않기 때문에 그것을 바꾸지 않습니다.

힌트 : 나는 카메론의 대답에 투표했다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top