I currently have a list containing items which have fields: "name, description, source, title, ...". I want to dump a list from this, but solely unique based on two keys, the name and description. Basically, I don't want items from the list with the same name and the same description, but if they have different names and the same description, then it's fine.
I looked up that using
list.select(x => x.Name).Distinct()
would give me a list with distinct name, but stacking them would violate having one of the unique keys different, and one the same.
I also took a look into hash sets, but I'm completely confused on how that works.
If anyone could help, it would be greatly appreciated.
If you're just looking for all distinct name/description combinations:
list.Select(x => new {x.Name, x.Description}).Distinct();
You can either use the following example taken from HERE:
IEnumerable<Person> filteredList = originalList
.GroupBy(person => person.Name)
.Select(group => group.First());
Or use DistinctBy from MoreLINQ NuGet available HERE
var uniqueData = list.Select(x => new
{
UniqueKey = x.Name + " " + x.Description,
Data = x,
}).GroupBy(x => x.UniqueKey)
.Select(g => g.First().Data)
.ToList();
You should probably use some unique/special character/string instead of " " to make sure UniqueKey is really unique.
Related
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
I seem to be running into an issue with what is probably a very simple task (forgive my newbie-ness with linq and c#).
I want to use linq to query an EF DB context. As part of this, I want to group by a few columns, then store these results into a list object.
I currently have this:
var Orders = orderSqlContext.OrderDetails
.GroupBy(x => new
{
x.OrderNumber,
x.OrderTotal
})
.Select(x => new
{
x.OrderNumber,
x.OrderTotal
}).ToList
I end up with errors on the two columns in the "select" portion above.
"OrderDetails does not contain a definition for OrderNumber and no extension method OrderNumber accepting a first argument of type IGrouping [...] could be found."
Basically, the OrderDetails context would normally return a list of orders with extra records for each line item on them. I want to also have a list of the distinct orders in that context.
Thank you!
You have to use the Key property of the group:
var Orders = orderSqlContext.OrderDetails
.GroupBy(x => new
{
x.OrderNumber,
x.OrderTotal
})
.Select(grp => new
{
grp.Key.OrderNumber,
grp.Key.OrderTotal
}).ToList();
it will be x.Key.OrderNumber and x.Key.OrderTotal. Read in the help how GroupBy works.
I have a List of Presidents:
var obj = new List<President>();
They have fields Name and BeginningGovernance.
The Name can be repeated in list. The BeginningGovernance cann't repeat.
I need take List of unique by Name Presidents with the oldest BeginningGovernance (if name repeated).
How can I do this with help of Linq?
Try GroupBy:
Group by Name
Pick up the right president among ones with the same Name
Materialize to List "I need take list..."
Implementation:
var result = obj
.GroupBy(president => president.Name)
.Select(chunk => chunk // among presidents who have the same name
.OrderBy(president => president.BeginningGovernance)
.First())
.ToList();
The accepted answer is fine. I'll just point out that you could write a query that is shorter and easier to understand by using this code:
https://github.com/morelinq/MoreLINQ/blob/8fbb540fd140b6d0008120c37abd00e129203cc6/MoreLinq/DistinctBy.cs
Your query would then be
presidents
.OrderBy(p => p.BeginningGovernance)
.DistinctBy(p => p.Name)
.ToList()
which is extremely easy to read and understand.
Exercise: Suppose we swapped the order of the OrderBy and DistinctBy; would the query still be correct? Why or why not?
I have a Linq query I'm not 100% sure of, can someone explain it in plain English what is happening
var duplicates = this.BedStays
.GroupBy(i => new { i.PatientClassificationCode, i.BedBandCode, i.BedLevelAddOnInd, i.ServiceCodeTypeCode, i.ServiceCode, i.DayRate })
.Where(g => g.Count() > 1)
.Select(g => g.Key).ToList();
It will give you all duplicate rows which have the same
PatientClassificationCode
BedBandCode
BedLevelAddOnInd
ServiceCodeTypeCode
ServiceCode
DayRate
It does this by grouping rows together which have the same criteria, and then only displaying the groups with more than one row (that is, duplicates).
var duplicates = this.BedStays
...Assigning to a var called "duplicates" from a property in this class called "BedStays."
.GroupBy(
...Grouping by a set of specific traits...
i =>
Called a single BedStay "i" (could have called it instead "aBedStay" or "bedStay" but the author went with "i")...
new { i.PatientClassificationCode, i.BedBandCode, i.BedLevelAddOnInd, i.ServiceCodeTypeCode, i.ServiceCode, i.DayRate })
...Creating a new object to sort by (First by the first member, then by the second, and so on and so forth)...
.Where(g => g.Count() > 1)
...Only picking the bedStay groupings where there's at least one matching member (I believe this is unneeded as all groupings, by definition, will only exist if from at least one grouping definition)...
.Select(g => g.Key).ToList();
...And finally we're only caring about the key, which is the grouping we defined when we new'd up the {i.Property, i.Property, i.Property} object. And we make it a list.
can someone explain it in plain English what is happening
Query is primarily listing all duplicates in your BedStays collection, by grouping on PatientClassificationCode, BedBandCode, BedLevelAddOnInd, ServiceCodeTypeCode, ServiceCode, DayRate fields.
i need help with this problem...
I have two lists of same objects "SearchResult", this object has an id attribute and a score attribute.
In both list can exist the same id, but with different score, so i need to create a new List that combines same id's but the score must be the sum of both scores and finally, the list get ordered by that final score.
How can i do that?
I search for a linq query, but i cant find any solution.
I hope you can help me, thanks!!!
Sounds like you might want something like:
var summed = results1.Concat(results2)
.GroupBy(r => r.Id)
.Select(g => new SearchResult {
Id = g.Key,
Score = g.Sum(x => x.Score)
});
You can use Union method from link. Example:
var mergedList = firstList.Union(secondList);