Kiểm tra xem danh sách <t> có chứa bất kỳ danh sách nào khác không


97

Tôi có một danh sách các tham số như sau:

public class parameter
{
    public string name {get; set;}
    public string paramtype {get; set;}
    public string source {get; set;}
}

IEnumerable<Parameter> parameters;

Và một mảng các chuỗi tôi muốn kiểm tra nó.

string[] myStrings = new string[] { "one", "two"};

Tôi muốn lặp lại danh sách tham số và kiểm tra xem thuộc tính nguồn có bằng với bất kỳ mảng myStrings nào hay không. Tôi có thể làm điều này với foreach's lồng nhau nhưng tôi muốn học cách thực hiện nó theo cách đẹp hơn vì tôi đã chơi với linq và thích các phương thức mở rộng trên enumerable như where, vv vì vậy foreachs lồng nhau chỉ cảm thấy sai. Có cách nào thanh lịch hơn linq / lambda / Deletegete để làm điều này không.

Cảm ơn

Câu trả lời:


207

Bạn có thể sử dụng một Any()séc lồng nhau cho séc này có sẵn trên bất kỳ Enumerable:

bool hasMatch = myStrings.Any(x => parameters.Any(y => y.source == x));

Thực hiện nhanh hơn trên các bộ sưu tập lớn hơn sẽ là chiếu parameterstới sourcevà sau đó sử dụng Intersectnội bộ sử dụng một HashSet<T>so thay vì O (n ^ 2) cho cách tiếp cận đầu tiên (tương đương với hai vòng lặp lồng nhau) bạn có thể kiểm tra trong O (n):

bool hasMatch = parameters.Select(x => x.source)
                          .Intersect(myStrings)
                          .Any(); 

Cũng như một nhận xét phụ, bạn nên viết hoa tên lớp và tên thuộc tính của mình để phù hợp với các nguyên tắc kiểu C #.


cảm ơn dường như là những gì tôi đang tìm kiếm tôi sẽ thử nó. Cần phải chơi xung quanh mặt chức năng của mọi thứ nhiều hơn một chút. liên quan đến việc viết hoa lớp và thuộc tính, tôi đã quên khi viết ví dụ trên.
gdp

1
Tại sao O (n ^ 2)? Không phải là O (n * m) như chúng ta đang nói về hai biến chứ không phải một? Vì m (các tham số) là một hằng số, nó giống như O (n). Tôi không thấy làm thế nào giao nhau nên nhanh hơn nhiều ở đây? Nhưng theo đồng ý, Intersect có tiềm năng nhanh hơn, nhưng không được đảm bảo.
Squazz vào

Bạn nói đúng rằng nó phải là O (n * m) - m không phải là hằng số - nó là kích thước của một trong các danh sách, mặc dù trong ví dụ cụ thể đưa ra, nó có thể là "2". Ngay cả các giá trị không đổi mặc dù không phải là không đáng kể trong thực tế - đối với tất cả các độ dài danh sách không tầm thường thì Intersectsẽ nhanh hơn - nếu các danh sách ngắn một cách tầm thường, điều đó không quan trọng bằng cách này hay cách khác (trong trường hợp đó, hiệu suất có lẽ không phải là mối quan tâm của bạn. )
BrokenGlass

làm thế nào bạn có thể tìm ra chỉ mục danh sách mà điều kiện trở thành đúng? Tôi có một danh sách với các câu. Tôi có một mảng với các từ cụ thể. Tôi muốn các chỉ mục của danh sách nếu câu có ít nhất một từ từ mảng. @BrokenGlass
kirushan

1
Hiệu suất khôn ngoan, sẽ không parameters.Any(x => myStrings.Contains(x.source));tốt hơn ví dụ đầu tiên của bạn?
Fluppe

3

Đây là một mẫu để tìm xem có các phần tử phù hợp trong danh sách khác không

List<int> nums1 = new List<int> { 2, 4, 6, 8, 10 };
List<int> nums2 = new List<int> { 1, 3, 6, 9, 12};

if (nums1.Any(x => nums2.Any(y => y == x)))
{
    Console.WriteLine("There are equal elements");
}
else
{
    Console.WriteLine("No Match Found!");
}

2
Lưu ý rằng nếu các danh sách liên quan lớn, điều này sẽ chậm hơn nhiều so với Intersectcách tiếp cận, vì nó là O (N * M) với kích thước của danh sách. (Đó là O (1) trong bộ nhớ.)
Jon Skeet

1

Nếu cả hai danh sách đều quá lớn và khi chúng ta sử dụng biểu thức lamda thì sẽ mất nhiều thời gian để tìm nạp. Tốt hơn nên sử dụng linq trong trường hợp này để tìm nạp danh sách tham số:

var items = (from x in parameters
                join y in myStrings on x.Source equals y
                select x)
            .ToList();
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.