Linq - Conditions for two categories in parallel
-
Hi
I’ve a question regarding linq,
I’ve a DB contains main items (Product) and internal item(properties)Class Product
{
String name
List<properties> propList { get; set; }
}Class properties
{
String name
String value
}I would like to know if it possible to create a query that apply on two or more categories on the same internal item at one time
Such as, if the product is “car” and if the car year is 2012 and color is “Red” I would like to get this recordList< Product > DB;
I know the syntax below is wrong, but this is the idea I wish to do
Enumerable< Product > itemQuery = from item in DB where item.name=="car"
where
(
from prop in item.propList
where (prop.name.Equals("Color") && prop.value == "Red") && (prop.name.Equals("Year") && prop.value == "2012")
select field
).Any()
select item; -
Hi
I’ve a question regarding linq,
I’ve a DB contains main items (Product) and internal item(properties)Class Product
{
String name
List<properties> propList { get; set; }
}Class properties
{
String name
String value
}I would like to know if it possible to create a query that apply on two or more categories on the same internal item at one time
Such as, if the product is “car” and if the car year is 2012 and color is “Red” I would like to get this recordList< Product > DB;
I know the syntax below is wrong, but this is the idea I wish to do
Enumerable< Product > itemQuery = from item in DB where item.name=="car"
where
(
from prop in item.propList
where (prop.name.Equals("Color") && prop.value == "Red") && (prop.name.Equals("Year") && prop.value == "2012")
select field
).Any()
select item;First off, this should have been posted in the LinQ forum LinQ Forum[^], but as you posted here, I will answer here. You can use the
Contains
keyword to find if the item's property list contains the required property, something like this:-var itemQuery = DB.Where((i) => i.name == "car" &&
i.propList.Contains((from prop in i.propList where prop.name == "Colour " && prop.value == "Red" select prop).FirstOrDefault()) &&
i.propList.Contains((from prop in i.propList where prop.name == "Year" && prop.value == "2012" select prop).FirstOrDefault()));although this looks ugly and seems to be a bit of a hack it will return the correct item. Hope this helps
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
-
Hi
I’ve a question regarding linq,
I’ve a DB contains main items (Product) and internal item(properties)Class Product
{
String name
List<properties> propList { get; set; }
}Class properties
{
String name
String value
}I would like to know if it possible to create a query that apply on two or more categories on the same internal item at one time
Such as, if the product is “car” and if the car year is 2012 and color is “Red” I would like to get this recordList< Product > DB;
I know the syntax below is wrong, but this is the idea I wish to do
Enumerable< Product > itemQuery = from item in DB where item.name=="car"
where
(
from prop in item.propList
where (prop.name.Equals("Color") && prop.value == "Red") && (prop.name.Equals("Year") && prop.value == "2012")
select field
).Any()
select item;Yes it is quite simple in one line.
var result = products.Where(item => item.Properties.Any(prop => prop.Name == name && prop.Value == value));
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
Hi
I’ve a question regarding linq,
I’ve a DB contains main items (Product) and internal item(properties)Class Product
{
String name
List<properties> propList { get; set; }
}Class properties
{
String name
String value
}I would like to know if it possible to create a query that apply on two or more categories on the same internal item at one time
Such as, if the product is “car” and if the car year is 2012 and color is “Red” I would like to get this recordList< Product > DB;
I know the syntax below is wrong, but this is the idea I wish to do
Enumerable< Product > itemQuery = from item in DB where item.name=="car"
where
(
from prop in item.propList
where (prop.name.Equals("Color") && prop.value == "Red") && (prop.name.Equals("Year") && prop.value == "2012")
select field
).Any()
select item;You could warp it in a method allowing you to keep calling in and further reducing the collection size.
public void test(IEnumerable<Product> products, string name, string value)
{
string name1 = "year";
string name2 = "color";
string value1 = "2012";
string value2 = "Red";//Just stream in what you need var result = Filter(Filter(products, name1, value1), name2, value2); } private IEnumerable<Product> Filter(IEnumerable<Product> products, string name, string value) { return products.Where(item => item.Properties.Any(prop => prop.Name == name && prop.Value == value)); }
You could also make the method an "Extension" allowing you to do more of this
products.Filter(name1, value1).Filter(name2, value2);
To make an extension create a separate file and use this:public static class ProductCollectionExtension
{
public static IEnumerable<T> Filter<T>(this IEnumerable<T> collection, string name, string value) where T : Product
{
return collection.Where(item => item.Properties.Any(prop => prop.Name == name && prop.Value == value));
}
}Now just include the namespace that you put this extension and any of your
Product
objects can then use the simplified notation, i.e.collection.Filter(name1, value1).Filter(name2, value2)....
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
You could warp it in a method allowing you to keep calling in and further reducing the collection size.
public void test(IEnumerable<Product> products, string name, string value)
{
string name1 = "year";
string name2 = "color";
string value1 = "2012";
string value2 = "Red";//Just stream in what you need var result = Filter(Filter(products, name1, value1), name2, value2); } private IEnumerable<Product> Filter(IEnumerable<Product> products, string name, string value) { return products.Where(item => item.Properties.Any(prop => prop.Name == name && prop.Value == value)); }
You could also make the method an "Extension" allowing you to do more of this
products.Filter(name1, value1).Filter(name2, value2);
To make an extension create a separate file and use this:public static class ProductCollectionExtension
{
public static IEnumerable<T> Filter<T>(this IEnumerable<T> collection, string name, string value) where T : Product
{
return collection.Where(item => item.Properties.Any(prop => prop.Name == name && prop.Value == value));
}
}Now just include the namespace that you put this extension and any of your
Product
objects can then use the simplified notation, i.e.collection.Filter(name1, value1).Filter(name2, value2)....
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
You could warp it in a method allowing you to keep calling in and further reducing the collection size.
public void test(IEnumerable<Product> products, string name, string value)
{
string name1 = "year";
string name2 = "color";
string value1 = "2012";
string value2 = "Red";//Just stream in what you need var result = Filter(Filter(products, name1, value1), name2, value2); } private IEnumerable<Product> Filter(IEnumerable<Product> products, string name, string value) { return products.Where(item => item.Properties.Any(prop => prop.Name == name && prop.Value == value)); }
You could also make the method an "Extension" allowing you to do more of this
products.Filter(name1, value1).Filter(name2, value2);
To make an extension create a separate file and use this:public static class ProductCollectionExtension
{
public static IEnumerable<T> Filter<T>(this IEnumerable<T> collection, string name, string value) where T : Product
{
return collection.Where(item => item.Properties.Any(prop => prop.Name == name && prop.Value == value));
}
}Now just include the namespace that you put this extension and any of your
Product
objects can then use the simplified notation, i.e.collection.Filter(name1, value1).Filter(name2, value2)....
Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
hi I’ve implement your idea and it work great, thank u! I have another question and hope you can assist The use will choose from UI several filter criteria, so the running filter should be dynamic and not hard coded Such as sometimes it could be collection.Filter(name1, value1) Or collection.Filter(name1, value1).Filter(name2, value2) collection.Filter(name1, value1).Filter(name2, value2). Filter(name3, value3) and so on how can I define by code the dynamic filter? Should I use recursive ? int interaction = #UserFilter.count; DoFilter(string name, string value) { While (interaction--) { collection.Filter(UserFilter[interaction].name, UserFilter[interaction].value) DoFilter(UserFilter[interaction].name, UserFilter[interaction].value); } } thanks ronen
-
hi I’ve implement your idea and it work great, thank u! I have another question and hope you can assist The use will choose from UI several filter criteria, so the running filter should be dynamic and not hard coded Such as sometimes it could be collection.Filter(name1, value1) Or collection.Filter(name1, value1).Filter(name2, value2) collection.Filter(name1, value1).Filter(name2, value2). Filter(name3, value3) and so on how can I define by code the dynamic filter? Should I use recursive ? int interaction = #UserFilter.count; DoFilter(string name, string value) { While (interaction--) { collection.Filter(UserFilter[interaction].name, UserFilter[interaction].value) DoFilter(UserFilter[interaction].name, UserFilter[interaction].value); } } thanks ronen
You are welcome. You could run it as they select the filter. In your code you would keep a filtered collection and keep adjusting it. If they hit "Clear" you would return the filter collection to the raw.
private IEnumerable<BusinessObject> _filteredCollection; //Initialized to entire set
private IEnumerable<BusinessObject> _rawData; //Initialized to entire set...
private void AdjustFilterCollection(string name, string value)
{
_filteredCollection = _filteredCollection.Filter(name, value);
}private void ClearFilter()
{
_filterCollection = _rawData;
}This method would then get called when the user updates the filter selection. You would then need to handle some UI post back (e.g. if using WPF implement the
INotifyPropertyChanged
)Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
-
You are welcome. You could run it as they select the filter. In your code you would keep a filtered collection and keep adjusting it. If they hit "Clear" you would return the filter collection to the raw.
private IEnumerable<BusinessObject> _filteredCollection; //Initialized to entire set
private IEnumerable<BusinessObject> _rawData; //Initialized to entire set...
private void AdjustFilterCollection(string name, string value)
{
_filteredCollection = _filteredCollection.Filter(name, value);
}private void ClearFilter()
{
_filterCollection = _rawData;
}This method would then get called when the user updates the filter selection. You would then need to handle some UI post back (e.g. if using WPF implement the
INotifyPropertyChanged
)Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.