web-dev-qa-db-ja.com

LINQを使用したリストのフィルタリング

プロジェクトオブジェクトのリストがあります。

IEnumerable<Project> projects

a ProjectTagsと呼ばれるプロパティとしてのクラス。これはint []です

filteredTagsという変数があり、これもint []です。

したがって、フィルタリングされたタグ変数が次のようになっているとします。

 int[] filteredTags = new int[]{1, 3};

リスト(projects)をフィルター処理して、フィルターにリストされているすべてのタグ(この場合はTags =プロパティ)。

Where()およびContains()を使用しようとしましたが、単一の値と比較している場合にのみ機能するようです。リストを別のリストと比較するためにこれをどのように実行しますか?

45
leora

編集:より良い、それはそのようにしてください:

var filteredProjects = 
    projects.Where(p => filteredTags.All(tag => p.Tags.Contains(tag)));

EDIT2:正直なところ、どちらが良いかわかりません。パフォーマンスが重要でない場合は、より読みやすいと思うものを選択してください。もしそうなら、どういうわけかそれをベンチマークする必要があります。


おそらくIntersectが進むべき道です:

void Main()
{
    var projects = new List<Project>();
    projects.Add(new Project { Name = "Project1", Tags = new int[] { 2, 5, 3, 1 } });
    projects.Add(new Project { Name = "Project2", Tags = new int[] { 1, 4, 7 } });
    projects.Add(new Project { Name = "Project3", Tags = new int[] { 1, 7, 12, 3 } });

    var filteredTags = new int []{ 1, 3 };
    var filteredProjects = projects.Where(p => p.Tags.Intersect(filteredTags).Count() == filteredTags.Length);  
}


class Project {
    public string Name;
    public int[] Tags;
}

最初は少し醜いようですが。 DistinctfilteredTagsに最初に適用すると、それらがリスト内ですべて一意であるかどうかわからない場合は、カウント比較が期待どおりに機能しません。

52
Dyppl

(少なくとも)すべてのフィルターされたタグを含む、または別の言い方で言うと、すべてのフィルターされたタグを含まないプロジェクトを除外する必要があります。したがって、Linq Exceptを使用して、含まれていないタグを取得できます。次に、Count() == 0を使用して、タグを除外しなかったものだけを含めることができます。

_var res = projects.Where(p => filteredTags.Except(p.Tags).Count() == 0);
_

または、Count() == 0!Any()に置き換えることで、少し速くすることができます。

_var res = projects.Where(p => !filteredTags.Except(p.Tags).Any());
_
3
Mariano Desanze
var result = projects.Where(p => filtedTags.All(t => p.Tags.Contains(t)));
2
Cheng Chen
var filtered = projects;
foreach (var tag in filteredTags) {
  filtered = filtered.Where(p => p.Tags.Contains(tag))
}

このアプローチの良い点は、検索結果を段階的に調整できることです。

1
Joh

http://code.msdn.Microsoft.com/101-LINQ-Samples-3fb9811b に基づいて、

EqualAllは、ニーズに最適なアプローチです。

public void Linq96() 
{ 
    var wordsA = new string[] { "cherry", "Apple", "blueberry" }; 
    var wordsB = new string[] { "cherry", "Apple", "blueberry" }; 

    bool match = wordsA.SequenceEqual(wordsB); 

    Console.WriteLine("The sequences match: {0}", match); 
} 
0
user3583337