Periksa apakah daftar <t> berisi daftar lain


97

Saya memiliki daftar parameter seperti ini:

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

IEnumerable<Parameter> parameters;

Dan serangkaian string yang ingin saya periksa.

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

Saya ingin mengulang daftar parameter dan memeriksa apakah properti sumber sama dengan salah satu array myStrings. Saya dapat melakukan ini dengan foreach bersarang tetapi saya ingin belajar bagaimana melakukannya dengan cara yang lebih baik karena saya telah bermain-main dengan LINQ dan seperti metode ekstensi pada enumerable seperti di mana dll sehingga foreachs bersarang hanya merasa salah. Apakah ada cara linq / lambda / delegete yang lebih elegan untuk melakukan ini.

Terima kasih

Jawaban:


208

Anda bisa menggunakan nested Any()untuk pemeriksaan ini yang tersedia di Enumerable:

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

Performa yang lebih cepat pada koleksi yang lebih besar adalah memproyeksikan parameterske sourcedan kemudian menggunakan Intersectyang secara internal menggunakan HashSet<T>jadi, bukan O (n ^ 2) untuk pendekatan pertama (setara dengan dua loop bersarang), Anda dapat melakukan pemeriksaan di O (n):

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

Juga sebagai komentar samping Anda harus menggunakan huruf besar nama kelas dan nama properti Anda agar sesuai dengan pedoman gaya C #.


terima kasih tampaknya apa yang saya cari saya akan mencobanya. Perlu bermain-main dengan sisi fungsional dari hal-hal yang sedikit lebih. Mengenai kapitalisasi kelas dan properti, saya memang lupa ketika menulis contoh di atas.
gdp

1
Mengapa O (n ^ 2)? Bukankah itu O (n * m) saat kita berbicara tentang dua variabel dan bukan satu? Karena m (paramet) adalah konstanta, itu sama dengan O (n). Saya tidak melihat bagaimana persimpangan harus lebih cepat di sini? Namun disepakati, Intersect berpotensi menjadi lebih cepat, namun tidak dijamin.
Squazz

Anda benar bahwa seharusnya O (n * m) - m bukan sebuah konstanta - ini adalah ukuran dari salah satu daftar, meskipun dalam contoh tertentu yang diberikan mungkin "2". Bahkan nilai konstan meskipun tidak dapat diabaikan dalam praktiknya - untuk semua panjang daftar yang tidak sepele, Intersectakan lebih cepat - jika daftarnya pendek, tidak masalah satu atau lain cara (dalam hal ini kinerja mungkin bukan urusan Anda sama sekali )
BrokenGlass

bagaimana Anda bisa mengetahui indeks daftar di mana kondisi menjadi benar? Saya punya daftar dengan kalimat. Saya memiliki array dengan kata-kata tertentu. Saya ingin indeks daftar jika kalimat tersebut memiliki setidaknya satu kata dari array. @BrokenGlass
kirushan

1
Dari segi kinerja, bukankah parameters.Any(x => myStrings.Contains(x.source));lebih baik dari contoh pertama Anda?
Fluppe

3

Berikut adalah contoh untuk mengetahui apakah ada elemen yang cocok di daftar lain

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
Perhatikan bahwa jika daftar yang terlibat besar, ini akan menjadi jauh lebih lambat daripada Intersectpendekatannya, karena O (N * M) dalam ukuran daftar. (Ini adalah O (1) dalam ingatan.)
Jon Skeet

1

Jika kedua daftar terlalu besar dan ketika kita menggunakan ekspresi lamda maka akan memakan waktu lama untuk diambil. Lebih baik menggunakan linq dalam kasus ini untuk mengambil daftar parameter:

var items = (from x in parameters
                join y in myStrings on x.Source equals y
                select x)
            .ToList();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.