GroupBy, OrderByDescending using Lambda in Linq - c#

I have a collection and I need to order it by descending date(DateProcessed field) using Linq, first I am grouping by two possible Keys: Booked or Empty. But the data it's not being ordered..
This is my expression:
IEnumerable<IGrouping<string, MyClassMongo>> sub = Model.MyCollection.GroupBy(f => f.IsBooked ? "Booked" : "Empty").OrderByDescending(f => f.FirstOrDefault().DateProcessed);
I'm confused because I am grouping first, I know that after grouping the collection is splitted in two(Booked and Empty) so I am not sure how to handle the sorting because I am grouping first

If you are querying in-memory collection, then just place ordering before grouping:
IEnumerable<IGrouping<string, MyClassMongo>> sub =
Model.MyCollection
.OrderByDescending(f => f.DateProcessed)
.GroupBy(f => f.IsBooked ? "Booked" : "Empty");
Items within each group will be sorted by DateProcessed.

if you want to first Group by and then sort the results within the Group. you can try some thing like below
Model.MyCollection
.GroupBy(f => f.IsBooked,
(f, g) => new{Key=f.DateProcessed, Group = g.OrderByDescending(c=>c.IsBooked)})
.OrderByDescending(f => f.Key);
PS: Code may have syntax issue not tested but the idea should be to create the key withing each group so we can order by

Related

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.

GroupBy and OrderBy using LINQ

I get data from my db using linq. I would like to use a GroupBy and an OrderBy on the same Request.
I actually have this code which doesn't work:
var mydata = _db.table1
.Join(_db.table2, h => h.col1, t => t.col2,
(h, t) => new ActivatedScripts()
{
col1 = h.col1, col2 = h.col2, col3 = (t.col3 == "Y"), col4 = ""
})
.GroupBy(z => z.col1).OrderBy(s => s.....);
the OrderBy(s => s...) suggest me all the LINQ method and a famous KEY which doesn't match any column in my code.
EDIT :
I follow the official tutorial to sort my table (http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application).
When I groupBy then sort (I tried to sort then groupby) I have an exception :
The GroupBy method returns a collection of groups. You can easily sort on the col1 column as that is the Key property of each group:
.OrderBy(s => s.Key)
If you want to sort on anything else, you have to get that value from the items in the group. If you for example know that a value is the same for all items in each group, you can get the value from the first item in the group:
.OrderBy(s => s.First().col2)
You can also use aggregates to calculate values using all the items in the group, for example sorting on the sum of the values:
.OrderBy(s => s.Sum(x => x.col2))
You can always order first and then group the ordered data:
.Join(...).OrderBy(x => x.col1).GroupBy(x => x.col2)

GroupBy and Sum

I read a lot of GroupBy + Sum topics but I didn't understand how to use it.
I have a list of contacts, and in this list, i want to get the state (which appears more).
So my code is:
contacts.GroupBy(i => i.Address.State.ToUpperInvariant());
In this GroupBy, I want to know the state that appears more (and remove the case of "" because empty state is not important to me).
How do I do it?
I was thinking in something like this:
contacts.GroupBy(i => i.Address.State.ToUpperInvariant()).Select(i => i.Max());
Thanks in advance!
You want something like:
var counts = contacts
.Where(c => c.State != string.Empty)
.GroupBy(i => i.Address.State, StringComparer.OrdinalIgnoreCase)
.Select(grp => new { State = grp.Key, Count = grp.Count());
GroupBy returns an IEnumerable<IGrouping<TKey, TSource>>. Since IGrouping<TKey, TSource> implements IEnumerable<TSource>, you can use the Count extension method to get the number of elements in the group.

LINQ group by and order by in C#

I need to convert my city list into group by state and order by city within it.
I tried below one but not able to get it right. Would appreciate any help on this.
cities.GroupBy(g => g.state).Select(o => o.OrderBy(c => c.cityname));
Try below code
cities.GroupBy(g => g.state)
.Select(o =>new {
State = o.Key,
Cities = o.OrderBy(c => c.cityname).Tolist()})
.Tolist();
cits.OrderBy(d => d.cityname).GroupBy(d => d.state).SelectMany(g => g).ToList();
1 - Order by cityname first.
2 - Then group them according to state. Since you order first, groups are still ordered with respect to cityname property.
3 - Convert to single list. Otherwise, you will end up with list of groups.
Should work. I also advice using camel case notation for naming your variables.
The ToLookup function may give you what you need.
cities.ToLookup(c => c.state, c => c.city);
This will create an IGrouping<string, string> where you can iterate through the Key values (states) and operate on a set of city values.
To sort it first, just do cities.OrderBy(c => c.state).ThenBy(c => c.city).
Do the orderby first:
cities.OrderBy(c=>c.cityname).GroupBy (c => c.state);
You might want to order the states to so.
cities.OrderBy(c=>c.cityname).GroupBy (c => c.state).OrderBy (g => g.Key);

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.

Categories