.NET에는 List a에 List b의 모든 항목이 포함되어 있는지 확인할 수있는 방법이 있습니까?


98

다음과 같은 방법이 있습니다.

namespace ListHelper
{
    public class ListHelper<T>
    {
        public static bool ContainsAllItems(List<T> a, List<T> b)
        {
            return b.TrueForAll(delegate(T t)
            {
                return a.Contains(t);
            });
        }
    }
}

그 목적은 목록에 다른 목록의 모든 요소가 포함되어 있는지 확인하는 것입니다. 이와 같은 것이 이미 .NET에 내장되어있는 것처럼 보일 것입니다. 그럴 경우 기능을 복제하고 있습니까?

편집 : Mono 버전 2.4.2 에서이 코드를 사용하고 있다고 미리 밝히지 않은 것에 대해 사과드립니다.



알고리즘은 2 차 O (nm)입니다. 목록이 정렬 된 경우 하나가 다른 목록의 하위 집합인지 테스트하는 것은 O (n + m) 시간 내에 가능해야합니다.
대령 패닉

답변:


177

.NET 3.5를 사용하는 경우 간단합니다.

public class ListHelper<T>
{
    public static bool ContainsAllItems(List<T> a, List<T> b)
    {
        return !b.Except(a).Any();
    }
}

여기에없는 요소가 있는지 확인합니다 b.a - 후 결과 반전.

메서드를 클래스보다 제네릭 으로 만드는 것이 약간 더 관습 적 이며 요구할 이유가 없습니다.List<T> 대신IEnumerable<T> 아마도 이것이 선호 될 것입니다.

public static class LinqExtras // Or whatever
{
    public static bool ContainsAllItems<T>(this IEnumerable<T> a, IEnumerable<T> b)
    {
        return !b.Except(a).Any();
    }
}

1
이것은 테스트되지 않았지만 b.Except (a) .Empty ();를 반환하지 않습니다. 훨씬 더 가독성이 좋습니까?
Nils

7
Empty ()가 부울을 반환하지 않는 것을 제외하고는. 항목이없는 IEnumerable <T>를 반환합니다.
Peter Stephens

2
Mono에서 LINQ to Objects를 사용할 수 있습니다.하지만 질문에 요구 사항을 명시하면 도움이 될 것입니다. 어떤 버전의 Mono를 사용하고 있습니까?
Jon Skeet

1
목록이 길이 n과 m이면이 알고리즘의 시간 복잡도는 얼마입니까?
대령 패닉

1
@ColonelPanic : 해시 충돌이 없다고 가정하면 O (n + m).
Jon Skeet

38

.NET 4에 포함됨 : Enumerable.All

public static bool ContainsAll<T>(IEnumerable<T> source, IEnumerable<T> values)
{
    return values.All(value => source.Contains(value));
}

35

재미로 @JonSkeet의 대답 을 확장 방법으로 사용하십시오.

/// <summary>
/// Does a list contain all values of another list?
/// </summary>
/// <remarks>Needs .NET 3.5 or greater.  Source:  https://stackoverflow.com/a/1520664/1037948 </remarks>
/// <typeparam name="T">list value type</typeparam>
/// <param name="containingList">the larger list we're checking in</param>
/// <param name="lookupList">the list to look for in the containing list</param>
/// <returns>true if it has everything</returns>
public static bool ContainsAll<T>(this IEnumerable<T> containingList, IEnumerable<T> lookupList) {
    return ! lookupList.Except(containingList).Any();
}

2
유사하게 : 포함 Any = public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Count() > 0; }. 나는 몇 가지 빠른 성능 비교를 시도 haystack.Count() - 1 >= haystack.Except(needle).Count();하고 Intersect더 나은 대부분의 시간을 할 것 같았다.
drzaus

4
쳇 ... 사용 Any()하지 Count() > 0: public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Any(); }
drzaus

0

다른 방법을 사용할 수도 있습니다. 같음을 재정의하고 이것을 사용하십시오.

public bool ContainsAll(List<T> a,List<T> check)
{
   list l = new List<T>(check);
   foreach(T _t in a)
   {
      if(check.Contains(t))
      {
         check.Remove(t);
         if(check.Count == 0)
         {
            return true;
         }
      }
      return false;
   }
}

2
list l = new List<T>(check);나는 이것이 컴파일 될 것이라고 생각하지 않는다. 만약 그렇다면, check이미리스트 처럼 그것의 완전히 불필요하다
Rohit Vipin Mathews
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.