LINQ'ya Göre Listede bir öğe bul?


226

Burada dizeler listesindeki bir öğeyi bulmak için basit bir örnek var. Normalde böyle yapmak için döngü veya anonim delege için kullanın:

int GetItemIndex(string search)
{
   int found = -1;
   if ( _list != null )
   {
     foreach (string item in _list) // _list is an instance of List<string>
     { 
        found++;
        if ( string.Equals(search, item) )
        {
           break;
        }
      }
      /* use anonymous delegate
      string foundItem = _list.Find( delegate(string item) {
         found++;
         return string.Equals(search, item);
      });
      */
   }
   return found;
}

LINQ benim için yeni. Listedeki öğeyi bulmak için LINQ kullanabilir miyim merak ediyorum? Mümkünse nasıl?


Bu harika. Ancak, bunların hepsi lamda ifade tarzıdır. Burada basit bir liste kullanıyorum. Liste, çeşitli özelliklere sahip bir sınıf olabilir ve bazıları arama için kullanılır. Yani "nereden ... nereden ... seç ..." gibi arama yapmak için herhangi bir LINQ yolu
David.Chu.ca

Hayır, üzgünüm. Bu yöntemlerin çoğu (First, Single, Any, ...) doğrudan bu forma çevrilemez.
R. Martinho Fernandes

Boşver, aslında birkaç dava için lambdaslardan kurtulabilirsin ...
R. Martinho Fernandes

Harika cevaplar! Sadece numaralandırma durumundan LINQ arama zevk almak istiyorum.
David.Chu.ca

Yanıtlar:


478

Birkaç yol var ( bunun tam bir liste olmadığını unutmayın ).

1) Single , tek bir sonuç döndürür, ancak birden fazla veya daha fazlasını bulamazsa bir istisna atar (bu, istediğiniz gibi olabilir veya olmayabilir):

string search = "lookforme";
List<string> myList = new List<string>();
string result = myList.Single(s => s == search);

Not SingleOrDefault()yerine bir istisna atma, referans türleri veya değer türleri için varsayılan değeri null adlı dönecektir hariç aynı davranacaktır.

2) Kriterlerinize uyan tüm öğeleri nereye iade edersiniz, böylece tek bir öğeyle IEnumerable alabilirsiniz:

IEnumerable<string> results = myList.Where(s => s == search);

3) İlk kriterleri eşleşen ilk öğeyi döndürür:

string result = myList.First(s => s == search);

Not FirstOrDefault()yerine bir istisna atma, referans türleri veya değer türleri için varsayılan değeri null adlı dönecektir hariç aynı davranacaktır.


35
Mükemmel cevap. SingleOrDefault'un seçim cevabım olduğunu buldum - Single ile aynı, ancak bulamazsa 'null' değerini döndürür.
Eddie Parker

2
Single () ya da SingleOrDefault () bilmiyordum. Çok kullanışlı.
draconis

Bu yöntemler ReadOnlyCollectionveya gibi diğer koleksiyonlarla da kullanılabilir ObservableCollectionmi?
yellavon

@yellavon bunlar uygulayan herhangi bir tipte uzatma yöntemleridir IEnumerable<T>veyaIQueryable<T>
Rex M

4
SingleOrDefault kullanımı hakkında dikkat edilmesi gereken bir şey, listede birden fazla eşleşme olması durumunda bir istisna atması nedeniyle, ilk eşleşme bulunduğunda FirstOrDefault'un aramayı durduracağı her öğeyi yinelemesi gerektiğidir. msdn.microsoft.com/en-us/library/bb342451(v=vs.110).aspx
DavidWainwright

73

Öğenin dizinini istiyorsanız, bunu yapar:

int index = list.Select((item, i) => new { Item = item, Index = i })
                .First(x => x.Item == search).Index;

// or
var tagged = list.Select((item, i) => new { Item = item, Index = i });
int index = (from pair in tagged
            where pair.Item == search
            select pair.Index).First();

İlk geçişte lambdadan kurtulamazsın.

Öğe yoksa bunun atılacağını unutmayın. Bu, nullable ints'a başvurarak sorunu çözer:

var tagged = list.Select((item, i) => new { Item = item, Index = (int?)i });
int? index = (from pair in tagged
            where pair.Item == search
            select pair.Index).FirstOrDefault();

Öğeyi istiyorsanız:

// Throws if not found
var item = list.First(item => item == search);
// or
var item = (from item in list
            where item == search
            select item).First();

// Null if not found
var item = list.FirstOrDefault(item => item == search);
// or
var item = (from item in list
            where item == search
            select item).FirstOrDefault();

Eşleşen öğe sayısını saymak istiyorsanız:

int count = list.Count(item => item == search);
// or
int count = (from item in list
            where item == search
            select item).Count();

Eşleşen tüm öğeleri istiyorsanız:

var items = list.Where(item => item == search);
// or
var items = from item in list
            where item == search
            select item;

Ve nullbu durumların herhangi birinde listeyi kontrol etmeyi unutmayın .

Veya (list ?? Enumerable.Empty<string>())yerine kullanın list.

Yorumlara yardım ettiği için Pavel'e teşekkürler.


2
İki puan. İlk olarak, burada gerçek bir ihtiyaç yoktur string.Equals- yanlış bir şey yoktur ==. İkincisi, FirstOrDefault(öğenin orada bulunmayabileceği durumlar için) ve Selectöğenin dizininin gerekli olduğu durumu (sorunun kendisinde bulunan örnekte olduğu gibi) kapsayacak şekilde indeksle de belirtirim.
Pavel Minaev

Henüz mutlu değilim. Örneğimde -1 dizini (bulunamadı) yok. Herhangi bir öneri?
R. Martinho Fernandes

İlk önce eğer ile varlığını kontrol etmenin yanı sıra.
R. Martinho Fernandes

Önce listenin boş olup olmadığını kontrol etmem gerekir mi?
David.Chu.ca

ArgumentNullExceptionKaynak null ise atar
R. Martinho Fernandes

13

Gerçekten bir ise List<string>, LINQ gerekmez, sadece kullanın:

int GetItemIndex(string search)
{
    return _list == null ? -1 : _list.IndexOf(search);
}

Öğenin kendisini arıyorsanız, şunu deneyin:

string GetItem(string search)
{
    return _list == null ? null : _list.FirstOrDefault(s => s.Equals(search));
}

1
İlk örneğin mantığını takiben _list.Find(search)ikincisi için kullanabiliriz .
jwg

12

Listedeki öğeyi veya gerçek öğenin kendisini istiyor musunuz (öğenin kendisini varsayalım).

İşte size birkaç seçenek:

string result = _list.First(s => s == search);

string result = (from s in _list
                 where s == search
                 select s).Single();

string result = _list.Find(search);

int result = _list.IndexOf(search);

Vay be ... bazı insanlar süper hızlı bir tetikleyici;)
Kelsey

dönüş değeri olarak endeks hakkında ne dersiniz?
David.Chu.ca

ve _list'in _list ... biçiminde _list'in boş olup olmadığını kontrol etmem gerekir mi?
David.Chu.ca

6

Bu yöntem daha kolay ve daha güvenli

var lOrders = new List<string>();

bool insertOrderNew = lOrders.Find(r => r == "1234") == null ? true : false


1
true : falseAşağıda ihtiyacımız bile olmadığını düşünüyorumbool insertOrderNew = lOrders.Find(r => r == "1234") == null;
Vbp

5

Nasıl IndexOf?

Belirtilen nesneyi arar ve listedeki ilk oluşumun dizinini döndürür

Örneğin

> var boys = new List<string>{"Harry", "Ron", "Neville"};  
> boys.IndexOf("Neville")  
2
> boys[2] == "Neville"
True

Değer listede yer almıyorsa -1 döndürdüğünü unutmayın

> boys.IndexOf("Hermione")  
-1

2

Ben tam olarak istediğim zaman istediğim verecek bir dizinli liste bir tür olan bir Sözlük kullanmak için kullanılır.

Dictionary<string, int> margins = new Dictionary<string, int>();
margins.Add("left", 10);
margins.Add("right", 10);
margins.Add("top", 20);
margins.Add("bottom", 30);

Örneğin, marj değerlerime erişmek istediğimde sözlüğüme hitap ediyorum:

int xStartPos = margins["left"];
int xLimitPos = margins["right"];
int yStartPos = margins["top"];
int yLimitPos = margins["bottom"];

Yani, ne yaptığınıza bağlı olarak, bir sözlük yararlı olabilir.


Farklı bir soruya harika bir cevap.
jwg

2

İşte LINQ kullanmak için yönteminizi yeniden yazmanın bir yolu:

public static int GetItemIndex(string search)
{
    List<string> _list = new List<string>() { "one", "two", "three" };

    var result = _list.Select((Value, Index) => new { Value, Index })
            .SingleOrDefault(l => l.Value == search);

    return result == null ? -1 : result.Index;
}

Böylece,

GetItemIndex("two")geri dönecek 1,

ve

GetItemIndex("notthere")dönecektir -1.

Referans: linqsamples.com


1

Bu kodu deneyin:

return context.EntitytableName.AsEnumerable().Find(p => p.LoginID.Equals(loginID) && p.Password.Equals(password)).Select(p => new ModelTableName{ FirstName = p.FirstName, UserID = p.UserID });

1

Listeden bir öğe bulmamız gerekirse, Findve FindAllextensions yöntemini kullanabiliriz , ancak aralarında küçük bir fark vardır. İşte bir örnek.

 List<int> items = new List<int>() { 10, 9, 8, 4, 8, 7, 8 };

  // It will return only one 8 as Find returns only the first occurrence of matched elements.
     var result = items.Find(ls => ls == 8);      
 // this will returns three {8,8,8} as FindAll returns all the matched elements.
      var result1 = items.FindAll(ls => ls == 8); 

1

Bu, Linq List aramanızdaki ilk veya varsayılan değeri almanıza yardımcı olacaktır

var results = _List.Where(item => item == search).FirstOrDefault();

Bu arama döndüreceği ilk veya varsayılan değeri bulur.


0

Nesne listesindeki bir nesneyi aramak istiyorsunuz.

Bu, Linq List aramanızdaki ilk veya varsayılan değeri elde etmenize yardımcı olacaktır.

var item = list.FirstOrDefault(items =>  items.Reference == ent.BackToBackExternalReferenceId);

veya

var item = (from items in list
    where items.Reference == ent.BackToBackExternalReferenceId
    select items).FirstOrDefault();

0

IEnumerable'dan bir MessageAction sınıfı almak için FirstOfDefault'u Where Linq uzantısıyla birlikte kullanabilirsiniz. Reme

var action = Message.Actions.Where (e => e.targetByName == className) .FirstOrDefault ();

nerede

İşlemleri Listele {get; Ayarlamak; }

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.