LINQでリスト内のアイテムを検索しますか?


226

ここに、文字列のリストから項目を見つける簡単な例があります。通常、私はforループまたは匿名デリゲートを次のように使用します。

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は私にとって新しいものです。LINQを使用してリスト内のアイテムを検索できるかどうか知りたいのですが。できればどうですか?


それは素晴らしいことです。ただし、これらはすべてラムダ式スタイルです。ここでは簡単なリストを使用しています。リストはいくつかのプロパティを持つクラスであり、いくつかは検索に使用されます。「で...どこ...選択... ..から」のように検索する任意のLINQの道だから、
David.Chu.ca

いや、ごめんなさい。これらのメソッドのほとんど(First、Single、Anyなど)は、そのフォームに直接変換できません。
R.マルティーニョフェルナンデス、

気にしないでください、実際にはいくつかのケースでラムダを取り除くことができます...
R.マルティーニョフェルナンデス

すばらしい答えです!列挙型のケースからLINQ検索の味を知りたいだけです。
David.Chu.ca 09/07/24

回答:


478

いくつかの方法があります(これが完全なリストではないことに注意してください)。

1)Singleは単一の結果を返しますが、1つまたは1つ以上しか検出しない場合は例外をスローします(必要な場合もそうでない場合もあります)。

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

Note SingleOrDefault()は同じように動作しますが、例外をスローする代わりに、参照型の場合はnull、値型の場合はデフォルト値を返します。

2)は、条件に一致するすべてのアイテムをどこで返すので、1つの要素を持つIEnumerableを取得できます。

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

3)Firstは、条件に一致する最初のアイテムを返します。

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

Note FirstOrDefault()は同じように動作しますが、例外をスローする代わりに、参照型の場合はnull、値型の場合はデフォルト値を返します。


35
すばらしい答えです。SingleOrDefaultが私の選択の答えであることがわかりました-Singleと同じですが、見つからない場合は「null」を返します。
エディパーカー

2
Single()もSingleOrDefault()も知りませんでした。非常に便利。
draconis 14

これらのメソッドは、ReadOnlyCollectionまたはのような他のコレクションでも使用できますかObservableCollection
yellavon 2014年

@yellavonこれらは、実装するすべてのタイプの拡張メソッドです。IEnumerable<T>またはIQueryable<T>
Rex M

4
SingleOrDefaultを使用する際の注意点の1つは、リストに複数の一致がある場合は例外をスローするため、最初の一致が見つかるとFirstOrDefaultが検索を停止するすべての項目を反復処理する必要があるということです。msdn.microsoft.com/en-us/library/bb342451(v=vs.110).aspx
DavidWainwright

73

要素のインデックスが必要な場合は、次のようにします。

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();

最初のパスではラムダを取り除くことはできません。

これは、アイテムが存在しない場合にスローされることに注意してください。これは、null許容のintに頼ることで問題を解決します。

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();

アイテムが必要な場合:

// 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();

一致するアイテムの数をカウントする場合:

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

一致するすべてのアイテムが必要な場合:

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

そしてnull、これらのケースのいずれかでリストを確認することを忘れないでください。

またはの(list ?? Enumerable.Empty<string>())代わりに使用しますlist

コメントを手伝ってくれたPavelに感謝します。


2
2点。まず、string.Equalsここで実際に使用する必要はありません==。何も問題はありません。次に、FirstOrDefault(項目がそこにない可能性がある場合のために)言及し、項目のSelectインデックスが必要な場合をカバーするインデックスを付けます(質問自体のサンプルにあるように)。
Pavel Minaev、2009

まだ満足していません。私の例では-1インデックス(見つかりません)はありません。なにか提案を?
R.マルティーニョフェルナンデス、

まず、ifでその存在を確認します。
R.マルティーニョフェルナンデス

最初にリストがnullかどうかを確認する必要がありますか?
David.Chu.ca、2009

選択はスローArgumentNullExceptionソースがnullの場合
R.マルティーニ・フェルナンデス

13

それが本当にList<string>あなたがLINQを必要としないものであるならば、単に使用してください:

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

アイテム自体を探している場合は、次のことを試してください。

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

1
最初の例のロジックに従って、_list.Find(search)2番目の例に使用できます。
jwg 2013

12

リスト内のアイテムを希望しますか、それとも実際のアイテム自体を希望しますか(アイテム自体を想定します)。

ここにあなたのためのたくさんのオプションがあります:

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);

おっと...一部の人々はトリガーの1つで超高速です;)
ケルシー

戻り値としてのインデックスはどうですか?
David.Chu.ca、2009

そして、_listがnullかどうかをfrom .. in _list ...の形式でチェックする必要がありますか?
David.Chu.ca、2009

6

この方法はより簡単で安全です

var lOrders = new List<string>();

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


1
true : false以下も同じように動作 する必要はないと思いますbool insertOrderNew = lOrders.Find(r => r == "1234") == null;
Vbp

5

いかがIndexOfですか?

指定されたオブジェクトを検索し、リスト内の最初の出現のインデックスを返します

例えば

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

リストに値がない場合は-1を返すことに注意してください。

> boys.IndexOf("Hermione")  
-1

2

以前は、インデックス付きリストの一種であるディクショナリを使用していました。これにより、欲しいときに欲しいものを正確に得ることができます。

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

たとえば、マージンの値にアクセスしたいときはいつでも、辞書をアドレスします。

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

ですから、あなたが何をしているのかに応じて、辞書は役に立ちます。


別の質問への素晴らしい答え。
jwg 2013

2

LINQを使用するようにメソッドを書き換える1つの方法を次に示します。

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;
}

したがって、それを

GetItemIndex("two")戻ります1

そして

GetItemIndex("notthere")戻り-1ます。

リファレンス:linqsamples.com


1

このコードを試してください:

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

リストから要素を見つける必要がある場合は、Findand FindAllextensionsメソッドを使用できますが、それらの間にはわずかな違いがあります。ここに例があります。

 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

これは、Linqリスト検索で最初の値またはデフォルト値を取得するのに役立ちます

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

この検索で​​は、返される最初の値またはデフォルト値が検索されます。


0

オブジェクトリストでオブジェクトを検索したい。

これは、Linqリスト検索で最初の値またはデフォルト値を取得するのに役立ちます。

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

または

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

0

FirstOfDefaultをWhere Linq拡張と共に使用して、IEnumerableからMessageActionクラスを取得できます。レメ

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

どこ

リストアクション{get; セットする; }

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.