Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Finding Items in a Collection that Match one of...

4.85/5 (6 votes)
19 Oct 2016CPOL1 min read 19.1K  
Use LINQ to get the members of a collection that match the members of another collection

Introduction

Recently, I have answered a couple of Quick Answers where the user wanted a list of items that match a condition from another collection (similar to SQL's IN operator. The trick to solving this is reversing the order of the operands in the Where Linq extension from the norm.

Using the Code

The normal structue of a Where predicate follows the pattern:

C#
myCollection.Where(item=>item.Property matches value)

where Property is the property you want to match to a particular value using whatever operator or method is appropriate to return the required result. However, what if value is a collection of values? The trick to extracting your items is basically to reverse the conditional statement, and, depending on the way the match is made, optionally apply an Any, All, or Contains method to the values collection. So the basic pattern becomes:

C#
myCollection.Where(item=>values.Any(value=>value matches item.Property));

Some Examples

Problem

Get all items from List1 that are one of the items in List2. Comparison should be case-insensitive. This is basically the same as a standard SQL IN clause:

SQL
SELECT Field FROM TABLE WHERE Field IN (value1, value2,....valueN)

Solution

C#
List<string> values = {value1, value2...valueN};
var results = table
    .Select(rec=>rec.field)
    .Where(field=>values.Contains(field, StringComparer.CurrentCultureIgnoreCase));

Problem

Get all items where the inventory_code is prefixed with one of a set of standard prefixes(strings).

Solution

C#
string[] prefixes = {"N01", "N02", "M01", "M02" };
var results = inventoryList
    .Where(item=>prefixes.Any(prefix=>item.inventory_code.StartWith(prefix)));

Problem

Get paragraphs that contain all of the pre-defined words.

Solution

This solution performs the trick twice. Upon separating out each paragraph, the Where is issued with the SearchWords array as the LHS of the condition. It then issues the All condition for each word in SearchWords with the words in the paragraph as the LHS of the condition.

C#
string[] searchwords = {....};
string[] paragraphs = {
    "The quick brown fox jumps over the lazy dog.",
    "The quick brown fox jumps over the lazy cat.\nNotice the substitution of 'cat' for 'dog'.",
    "The quick brown fox jumps over the lazy cat." };
string[] searchWords = { "FOX", "DOG" };
char[] wordDelimiters = { ' ', ',', '.', ';', ';','\n', '"', '\'' };
var results = paragraphs.Where(paragraph => searchWords
  .All(word => paragraph.Split(wordDelimiters, StringSplitOptions.RemoveEmptyEntries)
  .Contains(word, StringComparer.CurrentCultureIgnoreCase)));

As evidenced by these examples, the concept of using a pre-defined collection as the LHS operand in a Where albeit seeming a little unnatural, can be a useful tool.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)