Adding LINQ select queries to expression in loop - c#

I have a menu that dynamically populates a list of ToggleMenuFlyoutItems.
Now I want to filter a list based on the checked items in the ToggleMenuFlyoutItem list.
foreach(var treslag in TreeTypeFlyout.Items)
{
var flyoutItem = treslag as ToggleMenuFlyoutItem;
if (flyoutItem.IsChecked)
{
tempStems = tempStems.Where(x =>
x.SpeciesGroupName.ToLower() == flyoutItem.Text.ToLower());
}
}
What I expect from this code is that my linq query expression is populated with a bunch of where clauses, but it's always one expression. It does not seem to add an expression for each checked item.
What am I missing?

You can try to create a List to fill tempStems filter objects.
List<Type_of_tempStems> list =new List<Type_of_tempStems>();
foreach(var treslag in TreeTypeFlyout.Items)
{
var flyoutItem = treslag as ToggleMenuFlyoutItem;
if (flyoutItem.IsChecked)
{
list.AddRange(tempStems.Where(x => x.SpeciesGroupName.ToLower() == flyoutItem.Text.ToLower()));
}
}
If I understand correctly you can try to use lambda Where and Join to make it.
TreeTypeFlyout.Items
.Where(x=>x.IsChecked)
.Join(x=> x.Text.ToLower(),y=>y.SpeciesGroupName.ToLower(),(x,y)=>y);

Related

How to filter collection and it`s nested collection at the same time with the same filter?

I have collection which have other collection in it. And I need some elegant solution to the following:
I need to filter the first collection by it is inner collection. So in the first collection will remain only the objects that have nested collection which answer some filter. Next i want in the filtered first object to have inner collection filtered by the same filter.
Check the first level filtering:
collectionOne = collectionOne.Where(a => a.collectionTwo.Any(g => !string.IsNullOrEmpty(g.Value) && g.Value.Contains(stringValue)));
This way i will filter the first collection, but the inner one will be still not filtered. I want to filter the inner collection with the same filter for each object in the first one :) I can do this with some loop (afte the first filter), but maybe there is better way?
Possible solution:
foreach(var item in collectionOne)
{
item.collectionTwo = ... same filter
}
P.S. The reason I ask this is because there is also a switch case about the filter itself. So I will have to copy-paste the solution a couple times with different filter only.
That` why i do not prefer the loop.
Other Solution is to create Func which will be re-used in .Where clause, but this is also not efficient because each filter is kind of simple.
If understand it correctly, what you're looking for is:
collectionOne = collectionOne
.Where(filter)
.Select(item =>
{
item.collectionTwo = collectionTwo.Where(filter);
return item;
});
And, if you just want to select and not modify the items:
collectionOne = collectionOne
.Where(filter)
.Select(item =>
new X{
collectionTwo = collectionTwo.Where(filter),
// copy all other fields
});

make the remove from a list with condition in fastest way

Is there any alternative for deleting object from a list
instead of what I have done with foreach;
I mean I don't think that the way I do is the best way and optimize way
like this:
var allobj= .. //this a list of all object
var myobj= .. //this a list of my selected object
foreach (var inu in myobj.ToArray())
{
if (allobj.Where(p => p.UserName == inu.UserName).Count() != 0)
{
myobj.Remove(inu);
}
}
Other answers have drawback, and that's "creating new collection excluding selected items" instead of removing items from actual collection.
This approach does not copy from main collection, it will remove items from list directly at optimum speed.
You will generate hashset from your selected items so that you can lookup strings in hashset at constant speed.
// generate hashset from selected items
var set = new HashSet<string>(myobj.Select(x => x.UserName));
// remove all items from list.
allobj.RemoveAll(x => set.Contains(x.UserName));
If you want remove objects from myobj which UserName exists in allobj, then
var selected = myobj.Where(obj => allobj.Any(o => o.UserName == obj.UserName)).ToList();
You cannot remove from the list you are iterating into.
Anyway you can construct a new list containing all the elements where username is not present in the global list:
var finalList = myobj.Where(obj => allobj.Any(o => o.UserName !=
obj.UserName)).ToList();
If objects in those lists have the same reference, then to get all except selected items you can simply use:
var r = allItems.Except(selectedItems).ToList();
If they don't have the same reference, you can create the result this way:
var r = allItems.Where(x => !selectedItems.Any(y => y.UserName == x.UserName)).ToList();

Do an Include on list derived on DBQuery

I have an DbQuery and I want to fill another list with my DbQuery Item with some conditions like:
var carsList= DbContext.Cars.Where(e=> e.brand == brand);
var myFiltredcarList = new List<Car>();
foreach(var car in carsList)
{
//add items in list according to a condition
myFiltredcarList.Add(car);
}
I want to now if is possible to do something like :
myFiltredcarList.Include("Brands");
I cannot use my myFiltredcarList as List, I want to keep my carsList bidings to do an include in my filtred list(myFiltredcarList)
Is it possible ?
If it's what I need to change?
It's not possible.
First off, the Include method is defined on IQueryable<T>, and second it works only on LINQ To Entities queries, which your list apparently is not.
The only way could be if you can embed the filtering condition into original query like this
var myFiltredcarList= DbContext.Cars
.Include("Brands")
.Where(e => e.brand == brand && some condition)
.ToList();

lambda and linq expression

I am working on an asp.net mvc 5 application and I am trying to filter a list but I'll always get a bad result when I have a multiple selection. Im using a simple form with checkboxes to know which mission's criteria is selected.
My Database:
Table Mission has a list of criteria (Table: CriteriaList)
// public virtual ICollection<Criteria> CriteriaList { get; set; }
int[] CriteriaSelected = List of criteria selected in the form
var items = from i in db.Missions select i;
foreach (var criteriaID in CriteriaSelected)
{
items = items.Where(m => m.CriteriaList.Any(c => c.CriteriaID == criteriaID ));
}
I know it might be a problem with the 'and' operator used to concatenate the multiple "where" because I got the right result just for one checkbox selected. But I'm right now a little lost to do a multiple selection of criteria
Your help is really appreciated
I would try:
var items = db.Missions.Where(m => m.CriteriaList
.Any(c => CriteriaSelected.Contains(c.CriteriaID )));
You should get every mission where at least one of the criteria in the list is found in the selected criterias.
But be aware, that this is not with good performance with too much records because of lots of list searches.
#loiti was close, but deleted his answer instead of revising it. Here's what you need:
var criteriaSelectedIds = CriteriaSelected.Select(s => s.CriteriaID);
var items = db.Missions.Where(m =>
m.CriteriaList.Any(c =>
criteriaSelectedIds.Contains(c.CriteriaID)
)
);

How to change value of an object using linq

I have the following statment that if isdefault is true to this collection i need to set each object isDefault property to false.
custHead.lstCustomziation.Where(x => x.IsDefaultSelected == true).Select(x=>{x.IsDefaultSelected=false});
lstCustomziation is a collection.
LINQ is for querying. You should use a foreach loop to make changes:
foreach (var item in custHead.lstCustomziation.Where(x => x.IsDefaultSelected))
{
item.IsDefaultSelected = false;
}
That said, if IsDefaultSelected is false for the other items anyway, it may be simpler just to unconditionally set it:
foreach (var item in custHead.lstCustomziation)
{
item.IsDefaultSelected = false;
}
Linq is for querying, not updating. You can get a list of the items you want to change and then update using a normal loop:
var list = custHead.lstCustomziation.Where(x => x.IsDefaultSelected == true)
foreach(var item in list)
item.IsDefaultSelected=false;
As the Q of LINQ says, LINQ is designed for queries, not updates.
Just enumerate the LINQ result and apply your update.
Linq may have been initially created for querying but it has evolved and is used as functional programming methods, equivalents to "map", "reduce", and "filter" used in other languages.
In your example I would suggest:
var list = custHead.lstCustomziation.Where(x => x.IsDefaultSelected == true)
.Select(x=> TransformItem(x));
private XType TransformItem(XType item){
item.IsDefaultSelected=false;
return item;
}

Categories

Resources