<t> listesinin başka bir liste içerip içermediğini kontrol edin


97

Bunun gibi bir parametre listem var:

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

IEnumerable<Parameter> parameters;

Ve kontrol etmek istediğim bir dizi dizge.

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

Parametre listesi üzerinde yineleme yapmak ve kaynak özelliğinin herhangi bir myStrings dizisine eşit olup olmadığını kontrol etmek istiyorum. Bunu iç içe geçmiş foreach'lerle yapabilirim, ancak linq ile oynadığım ve numaralandırılabilir gibi uzatma yöntemlerini sevdiğim için nasıl daha iyi bir şekilde yapılacağını öğrenmek istiyorum. Bunu yapmanın daha zarif bir tercih edilen linq / lambda / delegete yolu var mı?

Teşekkürler

Yanıtlar:


208

Any()Bu kontrol için aşağıdakilerden herhangi birinde bulunan bir yuvalanmış kullanabilirsiniz Enumerable:

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

Daha büyük koleksiyonlarda daha hızlı performans, projeksiyon parametersyapmak sourceve sonra ilk yaklaşım için O (n ^ 2) yerine Intersectdahili olarak a kullanan kullanmak olacaktır HashSet<T>(iki iç içe döngüye eşdeğer), kontrolü O (n) olarak yapabilirsiniz:

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

Ayrıca bir yan yorum olarak, C # stil yönergelerine uymak için sınıf adlarınızı ve özellik adlarınızı büyük harfle yazmalısınız.


teşekkürler aradığım gibi görünüyor ben deneyeceğim. İşlerin işlevsel yönleriyle biraz daha oynamanız gerekiyor. Sınıf ve özelliklerin büyük harfle yazılmasıyla ilgili olarak, yukarıdaki örneği yazarken unutulmuştum.
gdp

1
Neden O (n ^ 2)? Bir değil iki değişkenden bahsettiğimiz için O (n * m) değil mi? M (parametreler) bir sabit olduğundan, O (n) ile aynıdır. Burada kesişmenin nasıl daha hızlı olması gerektiğini anlamıyorum? Ancak, Intersect'in daha hızlı olma potansiyeline sahip olduğu ancak garanti edilmediği kabul edildi.
Squazz

O (n * m) olması gerektiği konusunda haklısınız - m sabit değildir - verilen belirli örnekte "2" olsa bile, listelerden birinin boyutudur. Pratikte önemsiz olmasa da sabit değerler bile - önemsiz olmayan tüm liste uzunlukları için Intersectdaha hızlı olacaktır - listeler önemsiz derecede kısaysa, bir şekilde veya başka bir şekilde önemli değildir (bu durumda performans muhtemelen sizin endişeniz değildir zaten )
BrokenGlass

Koşulun doğru olduğu liste dizinini nasıl anlayabilirsiniz? Cümleler içeren bir listem var. Belirli kelimeleri içeren bir dizim var. Cümle diziden en az bir kelime içeriyorsa, listenin dizinlerini istiyorum. @BrokenGlass
kirushan

1
Performans açısından, parameters.Any(x => myStrings.Contains(x.source));ilk örneğinizden daha iyi olmaz mıydı ?
Fluppe

3

İşte başka bir listede eşleşme öğeleri olup olmadığını bulmak için bir örnek

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
Dahil edilen listeler büyükse, Intersectlistelerin boyutlarında O (N * M) olduğu için bu yaklaşımdan çok daha yavaş olacaktır . (Yine de hafızada O (1) var.)
Jon Skeet

1

Hem liste çok büyükse hem de lamda ifadesini kullandığımızda, o zaman getirilmesi uzun zaman alacaktır. Bu durumda parametre listesini getirmek için linq kullanmak daha iyidir:

var items = (from x in parameters
                join y in myStrings on x.Source equals y
                select x)
            .ToList();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.