.NET có cách nào để kiểm tra xem Danh sách a có chứa tất cả các mục trong Danh sách b không?


97

Tôi có phương pháp sau:

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);
            });
        }
    }
}

Mục đích của việc này là xác định xem một Danh sách có chứa tất cả các phần tử của một danh sách khác hay không. Có vẻ như với tôi rằng một cái gì đó như thế này đã được tích hợp sẵn trong .NET, có phải vậy không và tôi có đang sao chép chức năng không?

Chỉnh sửa: Tôi xin lỗi vì đã không nói trước rằng tôi đang sử dụng mã này trên phiên bản Mono 2.4.2.



Thuật toán của bạn là bậc hai O (nm). Nếu danh sách được sắp xếp, việc kiểm tra xem một danh sách có phải là tập con của danh sách khác không trong thời gian O (n + m).
Colonel Panic

Câu trả lời:


175

Nếu bạn đang sử dụng .NET 3.5, thật dễ dàng:

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

Điều này kiểm tra xem có bất kỳ phần tử bnào không a- và sau đó đảo ngược kết quả.

Lưu ý rằng sẽ hơi thông thường nếu tạo phương thức chung thay vì lớp và không có lý do gì để yêu cầu List<T>thay vì IEnumerable<T>- vì vậy điều này có thể sẽ được ưu tiên:

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

1
Điều này chưa được kiểm tra, nhưng sẽ không trả về b.Except (a) .Empty (); dễ đọc hơn?
Nils

7
Ngoại trừ Empty () không trả về boolean. Nó trả về IEnumerable <T> không có mục nào.
Peter Stephens

2
Tôi tin rằng bạn có thể sử dụng LINQ cho các đối tượng trong Mono ... nhưng sẽ rất hữu ích nếu bạn nêu các yêu cầu trong câu hỏi để bắt đầu. Bạn đang sử dụng phiên bản Mono nào?
Jon Skeet

1
Nếu danh sách có độ dài n và m, thì độ phức tạp về thời gian của thuật toán này là bao nhiêu?
Colonel Panic

1
@ColonelPanic: Giả sử không có va chạm băm, O (n + m).
Jon Skeet

37

Có trong .NET 4: Enumerable.All

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

35

Chỉ cho vui thôi, câu trả lời của @ JonSkeet như một phương pháp mở rộng:

/// <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
tương tự: Chứa bất kỳ = public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Count() > 0; }. Tôi đã thử một số so sánh hiệu suất nhanh với haystack.Count() - 1 >= haystack.Except(needle).Count();Intersectdường như hầu hết thời gian hoạt động tốt hơn.
drzaus

4
sheesh ... sử dụng Any()không Count() > 0: public static bool ContainsAny<T>(this IEnumerable<T> haystack, IEnumerable<T> needle) { return haystack.Intersect(needle).Any(); }
drzaus

0

Bạn cũng có thể sử dụng một cách khác. Ghi đè bằng và sử dụng cái này

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);Tôi không nghĩ rằng điều này sẽ biên dịch và nếu có, nó hoàn toàn hưởng ứng nhiệt liệt như checkđã là một danh sách
Rohit Vipin Mathews
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.