Reputation: 3023
I have a WinForms app in which I want to use a text box to take in a search query (e.g. mens black tshirt) and then filter a list of objects based on this search query.
The list of objects are orders objects. Each order object had several properties such as gender, size, colour etc.
If I get an array of strings by splitting the search query by the Space character, what is the best way to search for every item in this string array against every property in every order object in the list and return those that match all the strings in the string array?
For example if I search for "kids black medium", I only want to return orders that are kids AND black AND medium, so I would not want just black orders or just kids order etc.
Upvotes: 2
Views: 4580
Reputation: 101072
Given the following Order
class:
class Order
{
public string Size {get; set;}
public string Gender {get; set;}
public string Colour {get; set;}
public string Type {get; set;}
// List of "searchable" properties
public IEnumerable<string> GetTags()
{
return new []{Size, Gender, Colour, Type};
}
}
a simple approach could look like:
var list = new []
{
new Order {Size = "large", Gender = "women", Colour = "red", Type = "tshirt"},
new Order {Size = "large", Gender = "men", Colour = "black", Type = "tshirt"},
new Order {Size = "medium", Gender = "kids", Colour = "black", Type = "tshirt"},
new Order {Size = "medium", Gender = "kids", Colour = "black", Type = "shorts"},
new Order {Size = "medium", Gender = "men", Colour = "black", Type = "tshirt"}
};
var searchString = "kids black medium";
var searchValues = searchString.Split(new []{" "}, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray();
var result = from order in list
let tags = order.GetTags()
where searchValues.All(s => tags.Any(t => t == s))
select order;
result
now contains
You could also use Intersect
or a HashSet
to compare the search values/tags, but without further information of the requirements All
/Any
is a good-enough solution IMHO.
Upvotes: 3
Reputation: 25434
Try the following:
class Item
{
public bool Gender { get; set; }
public int Color { get; set; }
public string Type { get; set; }
public string[] GetKeyWords()
{
// Return properties as array of key words.
// You can cache the result for future use.
return default(string[]);
}
}
Now if you have the list of items and array of strings (keywords), you can write the following query:
var matches = from item in items
let itemKeyWords = item.GetKeyWords()
where keyWords.All(k => itemKeyWords.Any(c => c == k))
select item;
Upvotes: 1