Linq order by Area Name with one exception - linq

Hi say I have objects of type Area with Names:
Hokitika
Dunedin
Stewart Island
West Coast
Invercargill
and I want to order them by name I could go:
areas.OrderBy(a => a.Name)
to give me:
Dunedin
Hokitika
Invercargill
Stewart Island
West Coast
which is fine but what say I was wanting to make this to be an ordered list with the exception that the current users location was at the top so if they were in Invercargill the list would be:
Invercargill
Dunedin
Hokitika
Stewart Island
West Coast
Is this possible in Linq?

Sure. You can order by a bool:
areas.OrderByDescending(a => a.Equals(myArea, StringComparison.OrdinalIgnoreCase))
.ThenBy(a => a.Name);
If that doesn't work on your DB, you can try:
areas.Select(a => new { IsMyLocation = a.Equals(myArea, StringComparison.OrdinalIgnoreCase),
Area = a })
.OrderByDescending (a => a.IsMyLocation)
.Select(a => a.Area);

string currentLocation = "Invercatgill"; // for instance
var sortedresult = areas.OrderBy(a => a.Name.Equals(currentLocation) ? 0 : 1)
.ThenBy(a => a.Name);

Just another way to do it using Except
var currentLocation = new [] { user.CurrentLocation };
var otherAreas = areas.Except(currentLocation).OrderBy(x => x.Name)
var finalResult = currentLocation.Concat(otherAreas);

Related

LINQ join multi tables in Lambda ex

I hope that someone can help me out here or to point me in the right direction:
I have an issue with this script from my SQL. This is what I have from the database and it comes out with success.
Script for water counter that has reminder for active period:
Select *
from WaterCounters
join WaterUsages on WaterUsages.WaterCounterId = WaterCounters.Id
join Periodes per on per.PeriodeId=WaterUsages.PeriodeId
where per.IsApproved = 1
Now I am trying to "translate/convert" into a LINQ query:
var waterCounter = Context.MyWaterCounter.Join(xx).ToList...
I am sure that I am doing it right but please advice me in how to "join more than one table" - thanks in advance.
Best regards,
Kvolle
UPDATED:
this is my script so far:
var waterCounter = Context.MyWaterCounter.Join(
Context.MyWaterUsages
.Where(x => x.WaterCounterId ==x.WaterCounterId)
.ToList());
Here is as I see it one table.
The tables in the database look like this:
It will look something like below
var waterCounter = Context.MyWaterCounter.Join(
Context.MyWaterUsages,
(WC) => WC.WaterCounterId,
(WU) => WU.Id,
(WC, WU) => new { WaterCounter = WC, WaterUsage = WU}
)
.Join(
Context.Periodes.Where(p => p.IsApproved=1),
(WUC) => WUC.WaterUsage.PeriodeId,
(P) => P.PeriodeId,
(WUC, P) => new { WaterCounter = WUC.WaterCounter, WaterUsage = WUC.WaterUsage, Period = P}
)
.ToList());

Complex Linq Collection Query

I have this DB diagram and want to make a query to find all UserLists in a given region. RegionId is supplied.
So I can get all the departments by this code (may not be the best way..):
var region = context.Regions.Find(regionId);
IEnumerable<Department> departments = region.Areas
.SelectMany(a => a.Workplaces)
.SelectMany(w => w.Departments);
The Account can have many UserLists, and an Account can be linked to many Departments. Can someone formulate a queryto achieve this please?
for completeness the final code was:
List<UserList> query2 = context.Regions.Where(r => r.RegionId == regionId)
.SelectMany(r => r.Areas)
.SelectMany(a => a.Workplaces)
.SelectMany(w => w.Departments)
.SelectMany(d => d.AccountsAllowedToPost)
.Distinct()
.SelectMany(da => da.Lists).ToList();
You can use the let syntax (or the .Select method) to navigate the ManyToOne relationship.
var query =
from r in context.Regions
where r.RegionId == regionId
from a in r.Areas
from w in a.Workplaces
from d in w.Departments
from da in d.DepartmentAccounts
let acc = da.Account
from u in acc.UserLists
select u;
var query2 = context.Regions.Where(r => r.RegionId == regionId)
.SelectMany(r => r.Areas)
.SelectMany(a => a.Workplaces)
.SelectMany(w => w.Departments)
.SelectMany(d => d.DepartmentAccounts)
.Select(da => da.Account)
.SelectMany(acc => acc.UserLists);

LINQ Group By into a Dictionary Object

I am trying to use LINQ to create a Dictionary<string, List<CustomObject>> from a List<CustomObject>. I can get this to work using "var", but I don't want to use anonymous types. Here is what I have
var x = (from CustomObject o in ListOfCustomObjects
group o by o.PropertyName into t
select t.ToList());
I have also tried using Cast<>() from the LINQ library once I have x, but I get compile problems to the effect of it being an invalid cast.
Dictionary<string, List<CustomObject>> myDictionary = ListOfCustomObjects
.GroupBy(o => o.PropertyName)
.ToDictionary(g => g.Key, g => g.ToList());
I cannot comment on #Michael Blackburn, but I guess you got the downvote because the GroupBy is not necessary in this case.
Use it like:
var lookupOfCustomObjects = listOfCustomObjects.ToLookup(o=>o.PropertyName);
var listWithAllCustomObjectsWithPropertyName = lookupOfCustomObjects[propertyName]
Additionally, I've seen this perform way better than when using GroupBy().ToDictionary().
For #atari2600, this is what the answer would look like using ToLookup in lambda syntax:
var x = listOfCustomObjects
.GroupBy(o => o.PropertyName)
.ToLookup(customObject => customObject);
Basically, it takes the IGrouping and materializes it for you into a dictionary of lists, with the values of PropertyName as the key.
This might help you if you to Get a Count of words. if you want a key and a list of items just modify the code to have the value be group.ToList()
var s1 = "the best italian resturant enjoy the best pasta";
var D1Count = s1.ToLower().Split(' ').GroupBy(e => e).Select(group => new { key = group.Key, value = group.Count() }).ToDictionary(e => e.key, z => z.value);
//show the results
Console.WriteLine(D1Count["the"]);
foreach (var item in D1Count)
{
Console.WriteLine(item.Key +" "+ item.Value);
}
The following worked for me.
var temp = ctx.Set<DbTable>()
.GroupBy(g => new { g.id })
.ToDictionary(d => d.Key.id);

Groupby and where clause in Linq

I am a newbie to Linq. I am trying to write a linq query to get a min value from a set of records. I need to use groupby, where , select and min function in the same query but i am having issues when using group by clause. here is the query I wrote
var data =newTrips.groupby (x => x.TripPath.TripPathLink.Link.Road.Name)
.Where(x => x.TripPath.PathNumber == pathnum)
.Select(x => x.TripPath.TripPathLink.Link.Speed).Min();
I am not able to use group by and where together it keeps giving error .
My query should
Select all the values.
filter it through the where clause (pathnum).
Groupby the road Name
finally get the min value.
can some one tell me what i am doing wrong and how to achieve the desired result.
Thanks,
Pawan
It's a little tricky not knowing the relationships between the data, but I think (without trying it) that this should give you want you want -- the minimum speed per road by name. Note that it will result in a collection of anonymous objects with Name and Speed properties.
var data = newTrips.Where(x => x.TripPath.PathNumber == pathnum)
.Select(x => x.TripPath.TripPathLink.Link)
.GroupBy(x => x.Road.Name)
.Select(g => new { Name = g.Key, Speed = g.Min(l => l.Speed) } );
Since I think you want the Trip which has the minimum speed, rather than the speed, and I'm assuming a different data structure, I'll add to tvanfosson's answer:
var pathnum = 1;
var trips = from trip in newTrips
where trip.TripPath.PathNumber == pathnum
group trip by trip.TripPath.TripPathLink.Link.Road.Name into g
let minSpeed = g.Min(t => t.TripPath.TripPathLink.Link.Speed)
select new {
Name = g.Key,
Trip = g.Single(t => t.TripPath.TripPathLink.Link.Speed == minSpeed) };
foreach (var t in trips)
{
Console.WriteLine("Name = {0}, TripId = {1}", t.Name, t.Trip.TripId);
}

How do I group by a Nested property's Nested property (part II)

In a previous post (http://bit.ly/bbIthV) i asked how to Group a list of Persons by their nested Address.State, when Address might be null.
Jon Skeet gave a perfect answer to my question:
//Create a dummy replacement for when a person has no addresses
Address dummyAddress = new Address { State = "" };
people.GroupBy(p => (p.Addresses.GetFirstOrDefault() ?? dummyAddress).State);
But seeing the results, I see that I wasn't asking the right quesion.
If I have 6 people, each one living at n addresses, the above will only get 6 groups...whereas I should instead be getting a group of persons, grouped by the key State that could be found by:
var distinctAddresses = people.SelectMany(p=>p.Addresses).City).Distint();
I think the answer will involve a GroupJoin of some kind, but I haven't gotten very far...
//Back where I started:
var y = addresses.GroupJoin(persons,a => a.State, p => p.Addresses.FirstOrDefault(),
(a,p)=> p);
//Doesn't compile...
var y = addresses.GroupJoin(persons,a => a, p => p.Addresses, (a,p)=> p);
Does anybody have a suggestion on how to proceed?
Thank you very much!
It might be simpler using query syntax:
var q = from p in People
group p by p.Address.State into g
select g;
How about this?
var q =
(from p in people
from a in p.Addresses
group p by a.State ?? "")
.ToDictionary(x => x.Key, x => x.Distinct())

Resources