c# and LINQ - convert IGrouping to List - c#

I have the following code written to find common objects in a list of objects
https://dotnetfiddle.net/gCgNBf
..............................
var query = setOfPersons
.SelectMany(l => l.Select(l1 => l1))
.GroupBy(p => p.Id)
.Where(g => g.Count() == setOfPersons.Count);
After that, I need to convert "query" to a list of "Person" objects ( List ) to achieve something else.
I tried using "ToList()"... But it says:
" cannot convert IGrouping to a List ".
Can someone help me to fix it ?

Looking at your code it seems that what you are trying to achieve is to get the list of people that exist in each list. If so, you can use the following query:
var query = setOfPersons
.SelectMany(l => l.Select(l1 => l1))
.GroupBy(p => p.Id)
.Where(g => g.Count() == setOfPersons.Count)
.Select(x=>x.First()) // Select first person from the grouping - they all are identical
.ToList();
Console.WriteLine("These people appears in all set:");
foreach (var a in query)
{
Console.WriteLine("Id: {0} Name: {1}", a.Id, a.Name);
}
Here you select just a single item from each grouping, because they all are identical.

Related

OrderBy items inside GroupJoin queryable by string list

results = await query
.GroupJoin(_invitations.GetAll().AsNoTracking()
.Where(i => i.GroupId == groupId),
user => user.Id,
invitation => invitation.UserId,
(a, s) => new { User = a, Invitation = s})
.SelectMany(
ai => ai.Invitation.DefaultIfEmpty(),
(a, s) => new { Users = a.User, Invitations = s }
)
.Select(i => i.Users)
.Skip(skip)
.Take(take)
.ToListAsync();
Howdy. I have quite simple group join but I can't figure out how to sort invitations inside this group join. Problem is, I don't want to make simple orderBy(i => i.creationDate) but I want to do something like (but on queryable):
var list = new List<string> {"Fall","Mid","Spring"};
return _db.MiaLog1A.Where(m => m.Campus == selectedCampus)
.AsEnumerable()
.OrderBy(m => m.StudentName)
.ThenBy(m=> list.IndexOf(m.Term));
I need to order them by specific strings. Because I have a scenario where newest invitation isn't what I need. I want accepted invitation status first. Is there a way to do this?
I've tried things like that:
.OrderBy(i => sortOrderList.IndexOf(i.InvitationsStatus) in many places but it just throws.
Thank you in advance.
A pattern of
.OrderBy(m => m.StudentName)
.ThenBy(m => m.X == "y" ? 0 : (m.X == "x" ? 1:2))
Should translate if you want to sort by "y","x","z"
But I note that both examples you given; (fall, mid, spring) and (approved vs pending / not invited) are sorted in that order anyway.. you don't need to sort by the list index of these, you can just sort the strings ascending

Group by clause inside a nested list

I am trying to apply group by clause to a list element inside a parent list. How can I skip looping and write this within a single linq query
foreach (var record in marketRecordDTOs)
{
record.Sources = record.Sources
.GroupBy(i => i.SourceId)
.Select(i => i.FirstOrDefault())
.ToList();
}
So you can easily create an IEnumerable<> of all your new Sources:
var newSources = marketRecordDTOs.Select(record => record.Sources
.GroupBy(i => i.SourceId)
.Select(i => i.FirstOrDefault())
.ToList()
);
Though, I am not sure what you intend to do with it after that.

LINQ groupby search in contains

I have the following result:
var result = (from p1 in db.Table
select new ReportInform
{
DataValue = p1.DataValue,
SampleDate = p1.SampleDate
})
.Distinct()
.ToList();
// Next getting list of duplicate SampleDates
var duplicates = result.GroupBy(x => x.SampleDate)
.Where(g => g.Count() > 1)
.Select (x => x)
.ToList();
foreach (var r in result)
{
if (duplicates.Contains(r.SampleDate)) // get error here on incompatbility
{
r.SampleDate = r.SampleDate.Value.AddMilliseconds(index++);
}
}
Cannot convert from 'System.DateTime?' to 'System.Linq.IGrouping
That error is pretty clear but may not be at a first glance. As a programmer, you need to learn how to read, understand and make sense of compiler or runtime errors.
Anyhow it is complaining that it cannot convert DateTime? to System.Linq.IGrouping<System.DateTime, ReportInForm>. Why? Because this query returns an System.Linq.IGrouping<System.DateTime, ReportInForm>
var duplicates = result.GroupBy(x => x.SampleDate)
.Where(g => g.Count() > 1)
.Select (x => x)
.ToList();
The GroupBy method returns IGrouping<System.DateTime, ReportInForm> which has a Key and the Key is the thing you grouped by and a list of items in that group. You are grouping by SampleDate and checking if there are more than one items in that group and then selecting the group. Thus dulplicates has a list of IGrouping<System.DateTime, ReportInForm> and you are asking the runtime to check if it contains a DateTime? and it blows up at this line:
duplicates.Contains(r.SampleDate)
One way to fix this is: What you want to do is to select the key of that group. Thus do this:
.Select (x => x.Key)
If you are expecting duplicates to be of type List<DateTime?> then you meant to write this
.Select(x => x.Key)
instead of
.Select(x => x)

Remove every first element of grouped collection

I have a collection of elements and some of these elements are duplicating. I need to extract all records but only the first record if the record is one of a duplicate set.
I was able to group the elements and find all elements that have duplicates, but how to remove every first element of a group?
var records =
dbContext.Competitors
.GroupBy(x => x.Email)
.Select(x => new { Properties = x,
Count = x.Key.Count() })
.Where(x => x.Count > 1)
.ToList();
EDIT: Seems like it's impossible to accomplish this task with EF, because it fails to translate the desired linq expression to SQL. I'll be happy if someone offer different approach.
To exclude the first record from each email-address group with more than one entry, you could do this:
var records = dbContext.Competitors
.GroupBy(x => x.Email)
.SelectMany(x => (x.Count() == 1) ? x : x.OrderBy(t=>t).Skip(1))
.ToList();
This is the logic :
Group by a property > Select every Group > (Possibly) Sort that > Skip first one
This can be turned into some linq code like this :
//use SelectMany to flat the array
var x = list.GroupBy(g => g.Key).Select(grp => grp.Skip(1)).SelectMany(i => i);

LINQ OrderBy Name ThenBy ChildrenCollection.Name

Is there any way in LINQ to do an OrderBy and then do a ThenBy with the ThenBy using the children of the parent object to do the secondary ordering?
_repository.GetActiveDepartmentGroupsWithDepartments().OrderBy(c => c.DepartmentGroupName).ThenBy(c => c.Departments.OrderBy(d => d.DepartmentName))
In the above case, c.Departments is an EntityCollection.
BTW: When I try the above and then do a ToList() on it, I get this error:
DbSortClause expressions must have a type that is order comparable.
Parameter name: key
Thanks in advance for any help or guidance.
It seems like you're trying to get a list of all departments ordered by group then department name. If so, then you probably want to do something like this:
var res = from c in _repository.GetActiveDepartmentGroupsWithDepartments()
from d in c.Departments
orderby c.DepartmentGroupName, d.DepartmentName
select d;
Or in method syntax:
var res = _repository.GetActiveDepartmentGroupsWithDepartments()
.SelectMany(c => c.Departments, (c,d) => new { c, d })
.OrderBy(x => x.c.DepartmentGroupName)
.ThenBy(x => x.d.DepartmentName)
.Select(x => x.d);
Since Deparment is a collection, you have to transform it to a scalar to use it for sorting.
One option is to select a single entity to in the collection, e.g. the name of the first department:
_repository.GetActiveDepartmentGroupsWithDepartments()
.OrderBy(c => c.DepartmentGroupName)
.ThenBy(c => c.Departments
.OrderBy(d => d.DepartmentName)
.FirstOrDefault()
.DepartmentName
)
Another option is to order by a property of the collection itself, e.g. the number of departments:
_repository.GetActiveDepartmentGroupsWithDepartments()
.OrderBy(c => c.DepartmentGroupName)
.ThenBy(c => c.Departments.Count())

Categories