Listenin bir dize içeren öğe içerip içermediğini kontrol edin ve bu öğeyi alın


146

Bu soruya bir cevap ararken, LINQ kullanarak benzer sorulara rastladım, ancak onları tam olarak anlayamadım (ve böylece uygulayamadım), çünkü aşina olmadığım için. Temel olarak, istediğim şudur:

  1. Listedeki herhangi bir öğenin belirli bir dize içerip içermediğini kontrol edin.
  2. Varsa, o öğeyi alın.

Dürüst olmak gerekirse, bunu nasıl yapacağımı bilmiyorum. Ne gelebilir bu (elbette çalışmıyor):

if (myList.Contains(myString))
    string element = myList.ElementAt(myList.IndexOf(myString));

NEDEN işe yaramadığını biliyorum:

  • myList.Contains()Döndürmez true, çünkü listenin tüm bir öğesinin belirttiğim dizeyle eşleşip eşleşmediğini kontrol eder.
  • myList.IndexOf() bir olay bulamaz, çünkü yine olduğu gibi, dizeyle eşleşen bir öğeyi kontrol eder.

Yine de, bu sorunun nasıl çözüleceğine dair hiçbir fikrim yok, ama benimkine benzer sorularda önerildiği gibi LINQ kullanmak zorunda kalacağımı düşünüyorum. Bununla birlikte, burada durum buysa, cevaplayıcının bana örneklerinde LINQ kullanımını açıklamasını istiyorum (dediğim gibi, C # ile zamanımda bununla uğraşmadım). Şimdiden teşekkürler çocuklar (ve kızlar?).

EDIT: Bir çözüm buldum; sadece listede dolaşın, geçerli öğenin dizeyi içerip içermediğini kontrol edin ve sonra geçerli öğeye eşit bir dize ayarlayın. Merak ediyorum, bundan daha etkili bir yol var mı?

string myString = "bla";
string element = "";

for (int i = 0; i < myList.Count; i++)
{
    if (myList[i].Contains(myString))
        element = myList[i];
}

cevabımda bahsettiğim gibi, eski moda döngüler (sorunuz gibi) neredeyse her zaman en hızlı. Ama yeterince önemsiyorsanız test edebilirsiniz.
McKay

Listenizde dizenizi içeren birden fazla dize olabilir myString, geçerli döngünüzde son öğeyi alırsınız. İlkini veya sonunu bulmak istiyorsanız, sadece ilkini bulmak istiyorsanız, öğeyi bulduktan sonra döngüyü kırın.
Habib

Yanıtlar:


193

Linq'i burada kullanabilmelisiniz:

var matchingvalues = myList
    .Where(stringToCheck => stringToCheck.Contains(myString));

İlk eşleşen öğeyi iade etmek istiyorsanız:

var match = myList
    .FirstOrDefault(stringToCheck => stringToCheck.Contains(myString));

if(match != null)
    //Do stuff

1 - Ya değiştirmek Whereile FirstOrDefaultikinci durumdamyList.FirstOrDefault(stringToCheck => stringToCheck.Contains(myString))
Habib

Mükemmel cevap. Sadece meraktan: neden matchingderleyici tarafından belirlenir ( var)? Listemin tür olduğunu bildiğim Stringiçin string matching, bu durumda kullanmak güvenli olur mu?
Dimitris Iliadis

1
@JimIliadis "var" ve "string" bu durumda tamamen aynı anlama gelir - derleyici, sonucun sadece 'string' olabileceğini bilecek kadar zekidir . var gerçekten sadece bir kodlama tarzı şey (anonim türleri kullanmadığınızda)
Dave Bish

çok eski iş parçacığına yorum yaparken, ancak bu konuda bir istisna buldu. firstordefault () kullandığınızda, varsayılan değeri de döndürebildiğinden emin olun. diyelim ki bir empy dizesi geçiriyorsunuz, yani mystring = "" ve gösterilecek hiçbir şey beklemiyorsunuz, ancak yine de firstordefault'u seçtiğiniz için listenin ilk öğesini görüntüleyecektir.
Kirli Geliştirici

@DirtyDeveloper Bununla ne demek istediğinizden emin değilsiniz - hedef listede boş dizeler olmasa örneğiniz 'null değerini döndürür. FirstOrDefault () öğesini bir yapı türünde kullanmaya çalışıyorsanız haklısınız, örn. List <int> - FirstOrDefault () '0' değerini döndürür ve null değerini döndürmez - ancak, soru özellikle dizelerle ilgilidir
Dave Bish

29

Temel cevap şudur: döngü boyunca yineleme yapmanız ve belirtilen dizeyi içeren herhangi bir öğeyi kontrol etmeniz gerekir. Diyelim ki kod:

foreach(string item in myList)
{
    if(item.Contains(myString))
       return item;
}

Eşdeğer, ancak kısa kod:

mylist.Where(x => x.Contains(myString)).FirstOrDefault();

Burada x, yukarıdaki kodda "item" gibi davranan bir parametredir.


12
string result = myList.FirstOrDefault(x => x == myString)
if(result != null)
{
  //found
}

9
for (int i = 0; i < myList.Length; i++)
{
    if (myList[i].Contains(myString)) // (you use the word "contains". either equals or indexof might be appropriate)
    {
        return i;
    }
}

Eski moda döngüleri neredeyse her zaman en hızlısıdır.


Verimlilik peşinde olduğum için, bu yöntemin daha hızlı (dolayısıyla daha verimli) olmasını mı öneriyorsunuz?
Dimitris Iliadis

2
Mükemmel test etmedim, ama bunun daha hızlı olacağını tahmin ediyorum. Sadece bir şey bulana ve erken çıkana kadar listeden bir geçiş gerektirir (Linq seçenekleri iyi yazılmışsa yapabilir), linq yönteminin çağırma yüküne veya linq'in lambda ek yüküne sahip değildir. Bunlar büyük endişe nedenleri değildir, ancak bazı performans vuruşlarına neden olabilir.
McKay

List.Equals () neden kullanılmıyor?
F8ER

@ V.7 Çünkü sadece listedeki bir öğenin bir alt dize içerip içermediğini bilmek istiyor. list.equals ["abc", "def", "ghi"] işi için OP'nin tanımladığı şekilde "hi" içermiyor. list.equals doğru veri tiplerini bile almaz.
McKay

6

Dizenizi içeren dizelerin bir listesini istiyorsanız:

var newList = myList.Where(x => x.Contains(myString)).ToList();

Başka bir seçenek Linq FirstOrDefault kullanmaktır

var element = myList.Where(x => x.Contains(myString)).FirstOrDefault();

ContainsYöntemin büyük / küçük harfe duyarlı olduğunu unutmayın .


1
Büyük / küçük harfe duyarlı hakkında hatırlatma, StringComparison.InvariantCultureIgnoreCase uygulayın
JoshYates1980

2

Linq'in FirstOrDefaultuzantı yöntemini kullanabilirsiniz :

string element = myList.FirstOrDefault(s => s.Contains(myString));

Bu, alt dizeyi içeren yumruk öğesini myStringveya nullböyle bir öğe bulunmazsa döndürülür .

İhtiyacınız olan tek şey dizinse, List<T>sınıfın FindIndexyöntemini kullanın :

int index = myList.FindIndex(s => s.Contains(myString));

Bu, alt dizeyi içeren yumruk öğesinin dizinini myStringveya -1böyle bir öğe bulunmazsa döndürülür .


2

Burada çok iyi cevaplar var, ancak aşağıdaki gibi Var olanları kullanarak basit bir cevap kullanıyorum :

foreach (var setting in FullList)
{
    if(cleanList.Exists(x => x.ProcedureName == setting.ProcedureName)) 
       setting.IsActive = true; // do you business logic here 
    else
       setting.IsActive = false;
    updateList.Add(setting);
}

2

Böyle bir şey kullanabilmelisin, benim için iyi çalıştı:

var valuesToMatch = yourList.Where(stringCheck => stringCheck.Contains(myString));

ya da bunun gibi bir şey, eğer eşleşmediği yere bakmanız gerekiyorsa.

 var valuesToMatch = yourList.Where(stringCheck => !stringCheck.Contains(myString));

1

kullanabilirsiniz

var match=myList.Where(item=>item.Contains("Required String"));
foreach(var i in match)
{
//do something with the matched items
}

LINQ, herhangi bir veri koleksiyonunu "sorgulamak" için olanak sağlar. Bir koleksiyonda (burada dizelerin koleksiyonu (liste)) bir veritabanı sorgusu (select, where, vb.) Gibi sözdizimini kullanabilirsiniz.

bu yüzden "beni listeden ürün al"

"lambda ifadesi" kullandığınız yer içinde

kısaca lambda ifadesinin şöyle bir şey olduğunu söylemek için (input parametresi => return değeri)

yani "item" parametresi için "item.Contains (" zorunlu dize ")" döndürür. Bu nedenle, öğe dizeyi içeriyorsa true değerini döndürür ve bu nedenle, koşulu karşıladığından beri listeden seçilir.


1

Basit tutmak için bunu kullanın;

foreach(string item in myList)//Iterate through each item.
{
 if(item.Contains("Search Term")//True if the item contains search pattern.
 {
   return item;//Return the matched item.
 }
}

Alternatif olarak, bunu for döngüsü ile yapmak için şunu kullanın;

    for (int iterator = 0; iterator < myList.Count; iterator++)
    {
        if (myList[iterator].Contains("String Pattern"))
        {
            return myList[iterator];
        }
    }

Sadece işaret etmek için, kod satırlarından birini bir uç braketi kaçırdınız .. if (item.Contains ("Arama Terimi"))
Alex

0

Kod aşağıda birisine yardımcı olacağını umuyoruz diğer cevaplarda bool seçeneği görmedim.

Sadece kullan Any()

string myString = "test";
bool exists = myList
             .Where(w => w.COLUMN_TO_CHECK.Contains(myString)).Any();

0

Herhangi, Nerede, İlk ve İlk Veya Varsayılan'ı birleştirmek mümkündür; ya da gerekli olana bağlı olarak yüklemi bu yöntemlerden herhangi birine yerleştirebilirsiniz.

Herhangi bir eşleşme bulunmadığında bir istisna atılmak istemiyorsanız, muhtemelen First kullanmaktan kaçınmalısınız. FirstOrDefault, eşleşme bulunmazsa türün varsayılanını döndüreceğini bildiğiniz sürece genellikle daha iyi bir seçenektir (dizenin varsayılan değeri null, int 0, bool false, vb.).

using System.Collections.Generic;
using System.Linq;


bool exists;
string firstMatch;
IEnumerable<string> matchingList;

var myList = new List<string>() { "foo", "bar", "foobar" };

exists = myList.Any(x => x.Contains("o"));
// exists => true

firstMatch = myList.FirstOrDefault(x => x.Contains("o"));
firstMatch = myList.First(x => x.Contains("o"));
// firstMatch => "foo"

firstMatch = myList.First(x => x.Contains("dark side"));
// throws exception because no element contains "dark side"

firstMatch = myList.FirstOrDefault(x => x.Contains("dark side"));
// firstMatch => null

matchingList = myList.Where(x => x.Contains("o")); 
// matchingList => { "foo", "foobar" }

Bu kodu test edin @ https://rextester.com/TXDL57489

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.