List Filtering in Linq - c#

I have two lists. One is a list of Ids.
I've to filter the second list which is having the Ids in the former list only.
For that, I've written the below code
var Clientidlist = list.GroupBy(p => new {p.CompanyName, p.UserId})
.Select(s => s.Min(m => m.Id));
var olist = list.Where(x => Clientidlist.Contains(x.Id))
.OrderBy(x=>x.CompanyName).ToList();
But I think there something wrong in it. Can anyone help me?

Related

How to compare list anonymous type to another list

I am trying to use Except to compare two list but one is an anonymous type.
For Example:
var list1 = customer.Select(x => new { x.ID, x.Name }).ToList();
var list2 = existcustomer.Select(x => x.ID).ToList();
And I trying to compare two list IDs and return a list of list one name.
My code:
var checkIfCustomerIdNotExist = list1.Where(x => x.ID.ToList().Except(list2)).Select(x => x.Name).ToList();
I am wondering if there is any workaround.
I'd advise using a dictionary instead of a List
//create a dictionary of ID to name
var customerDict = customer.ToDictionary(x => x.ID, x => x.Name);
//get your list to compare to
var list2 = existcustomer.Select(x => x.ID).ToList();
//get all entries where the id is not in the second list, and then grab the names
var newNames = customerDict.Where(x => !list2.Contains(x.Key)).Select(x => x.Value).ToList();
In general it's good to think about what data structure suits your data the best. In your case list1 contains a list of tuple where ID needs to be used to find Name - using a data structure more suited to that (A dictionary) makes solving your problem much easier and cleaner
Note, the solution assumes ID is unique, if there are duplicate IDs with different names you might need a Dictionary<string, List< string >> instead of just a Dictionary<string,string> - but that would probably require more than just a single line of linq, code would be fairly similar though

Linq Order By Contains List

I have a List of ints that model.SelectedIngredients and in this example the list contains the values [15128, 4593,15046,]. I use this list then as a filter in my Linq query as follows:
List<INGREDIENT> selectedIngredients = db.INGREDIENT.Where(i => model.SelectedIngredients.Contains(i.IngredientId)).ToList();
However, this sorts the results by IngredientId ascending as default[4593,15046,15128].
What I would like is to get the selectedIngredients back in the same order as they are in model.SelectedIngredients.
I know I could do it in a for loop but I just wondered if there was a way I could do it within the Linq query?
Thanks
You can acomplish this quite easy by using the index of your list with ids.
List<INGREDIENT> selectedIngredients = db.INGREDIENT
.Where(i => model.SelectedIngredients.Contains(i.IngredientId))
.AsEnumerable()
.OrderBy(i => model.SelectedIngredients.IndexOf(i.IngredientId))
.ToList();
List<INGREDIENT> selectedIngredients = db.INGREDIENT
.Where(i => model.SelectedIngredients.Contains(i.IngredientId))
.orderBy(p=>p.Id).ToList();
This is the default one. Determine in the first place by which it is sorted and then order by it.

Query an XML using LINQ and excluding where an Attribute value is equal to that of an Element

I have a LINQ query against an XML, that gives me a list of nested lists, each sublist being a list of an elements("row") attributes.
var items = loadbodies.Descendants("row").Select(a => a.Attributes().Select(b => b.Value).ToList()).ToList();
This works as intended but, what I actually need to is query this against another list of values so as not to have sublists added where one of the elements attributes("messageID") is on the second list. I can do this for one value but need to check it against the entire second list.
The query to exclude a single sublist by a single hardcoded value from the second list is below.
var items = loadbodies.Descendants("row").Where(c => (string)c.Attribute("messageID") != "avaluefromthesecondlist").Select(a => a.Attributes().Select(b => b.Value).ToList()).ToList();
Any help would be much appreciated.
Just use Contains. Note that splitting lines helps readability considerably:
var ids = ...; // Some sequence of ids, e.g. a List<string> or HashSet<string>
var items = loadbodies
.Descendants("row")
.Where(row => ids.Contains((string) row.Attribute("messageId")))
.Select(a => a.Attributes()
.Select(b => b.Value)
.ToList())
.ToList();
Note that you could use a Join call too... but so long as you've got relatively few IDs, this should be fine.

best way to receive a list of objects from list of KeyValuePair?

I have a list of KeyValuePairs and I want to filter it based on the key value so eventually I will get a list of values which is filtered (meaning - will not contain all the values that were in the original list).
I guess maybe the best way is some form of Lambda expression but I am not sure how to achieve it.
Thanks,
Alon
Try this:
var values = list.Where(x => x.Key == "whatever").Select(x => x.Value);
This will give you a filtered list of the values only.
Obviously you can change the way you filter your keys.
Use the following:
var filteredList = list.Where(x => x.Key == "Key");
What you're looking for some combination of LINQ extension methods (which depends on what you're exactly trying to do).
For example if I had a List of fruits to their colors and wanted to get a collection of which fruits are red, I would do something like:
var fruits = new List<KeyValuePair<string,string>>() {
new KeyValuePair<string,string>("Apple", "Green"),
new KeyValuePair<string,string>("Orange", "Orange"),
new KeyValuePair<string,string>("Strawberry", "Red"),
new KeyValuePair<string,string>("Cherry", "Red")
};
var redFruits = fruits.Where(kvp => kvp.Value == "Red").Select(kvp => kvp.Key);
// this would result in a IEnumberable<string> { "Strawberry", "Cherry" }

SelectMany Three Levels Deep

I can flatten the results of a child collection within a collection with SelectMany:
// a list of Foos, a Foo contains a List of Bars
var source = new List<Foo>() { ... };
var q = source.SelectMany(foo => foo.Bar)
.Select(bar => bar.barId)
.ToList();
this gives me the list of all Bar Ids in the Foo List. When I attempt to go three levels deep the incorrect result is returned.
var q = source.SelectMany(foo => foo.Bar)
.SelectMany(bar => bar.Widget)
.Select(widget => widget.WidgetId)
.ToList();
How should I be using SelectMany to get the list of all Widgets in all Bars in my list of Foos?
Edit
I miss-worded the above sentence, but the code reflects the goal. I am looking for a list of all Widget Ids, not widgets.
An "incorrect" result is not all of the widget ids are returned.
Your query is returning all the widget IDs, instead of all the widgets. If you just want widgets, just use:
var q = source.SelectMany(foo => foo.Bar)
.SelectMany(bar => bar.Widget)
.ToList();
If that's still giving "the incorrect result" please explain in what way it's the incorrect result. Sample code would be very helpful :)
EDIT: Okay, if you want the widget IDs, your original code should be fine:
var q = source.SelectMany(foo => foo.Bar)
.SelectMany(bar => bar.Widget)
.Select(widget => widget.WidgetId)
.ToList();
That could also be written as
var q = (from foo in source
from bar in foo.Bar
from widget in bar.Widget
select widgetId).ToList();
if you like query expression format.
This really should work - if it's not working, that suggests there's something wrong with your data.
We should have checked before - is this just LINQ to Objects, or a fancier provider (e.g. LINQ to SQL)?
var q = (
from f in foo
from b in f.Bars
from w in b.Widgets
select w.WidgetId
).ToList();
Also note that if you want the unique list, you can do .Distinct().ToList() instead.
var q = source.SelectMany(foo => foo.Bar)
.SelectMany(bar => bar.Widget,(bar,widget) => widget.WidgetId)
.ToList();
we can call this overload of SelectMany() with allow us to specify the projection using lambda experession

Categories