I have values in a list:
List1
ID groupID testNo
1 123 0
2 653 1
3 776 6
4 653 0
I want to write a T-Sql or linq or lambda expression, so that whenever there is a duplicate it should pick the one with value !=0
I am using this expression but it is basically not giving the results I want.
var list2 = list1.GroupBy(x => x.testNo).Select(y => y.First());
How can I get the results so groupID 653 is chosen with testNo 1 with rest of the records?
There are a few approaches you could take. I don't know if any of them are full proof. One would be to do an OrderBy on testNo so that items with a non zero testNo will come up before those with 0.
var list2 = list1.Orderby(y => y.testNo).GroupBy(x => x.testNo).Select(z => z.FirstOrDefault());
If you can guarantee that testNo = 0 only occurs for dupes then the easiest way is just to use a where.
var list2 = list1.Where(x => x.testNo > 0).First();
This should give you the desired results:
var list2 = list1.GroupBy(x => x.groupID)
.Select(x => list1.Single(item => item.groupID == x.Key
&& item.testNo == x.Max(y => y.testNo)))
.ToList();
Basically, group by groupID and then select each item from the original list1 that matches the distinct groupID and has the max value for testNo for that groupID.
var result = list.GroupBy(x => x.groupID).Select(g => g.Count() == 1 ? g.First() : g.First(x => x.testNo != 0));
Related
var sameItems = items
.Where(x => x.Group != null)
.GroupBy(x => x.Group)
.Select(x => x.ToList())
.Where(x => x.All(y=> y.Status == 1)); // Not working :(
Item Group Status
Item1 1 1
Item2 1 2
Item3 1 1
Item4 2 1
Item5 2 1
So I would like to return items 4 and 5.
First I want to group by group number, and return items only those that have the same status of 1 and belong to the same group. Items 1, 2, and 3 belong to the same group, but not all have the status 1, so I want to exclude them.
Check the example here, it might help you:
dotnetfiddle example
It seems to work as you expected, you might need to dismantle the group hierarchy if you just want to use them as a list.
var sameItems = items
.Where(x => x.Group != null)
.GroupBy(x => x.Group)
.Select(x => x.ToList())
.Where(x => x.All(y => y.Status == 1))
.SelectMany(x => x);
foreach (var sameItem in sameItems)
{
Console.WriteLine(sameItem.Item);
}
I have tested your code, if your items really have the values you say they have (Would be great to see) then the LINQ query gives you an array with items 4 and 5, so what exactly is the problem?
I am looking for a way in LINQ to get a max Id record by using 'Group By' clause
Consider the following Sample data
Table: ProcessAud
ProcessSeq ProjectSeq ProjectValue Active
11 1 50000 Y
12 1 10000 Y
13 2 70000 Y
14 2 90000 Y
In which I want to get two records as a list such that is second and fourth
records (i.e) ProcessSeq 12 and 14. And I tried it like following
var ProcessAudList = ProcessAudService.FilterBy(x => x.Active == "Y"
).GroupBy(x => x.ProjectSeq).Max().ToList();
It is not working properly, So how to do it in LINQ. Please anybody help.
You want to pick top record from each group.
var ProcessAudList = ProcessAudService.Where(x => x.Active == "Y")
.GroupBy(x => x.ProjectSeq, (key,g)=>g.OrderByDescending(e=>e.ProjectValue).First());
Check demo code
When you use GroupBy extension, method will return you IGrouping instance and you should query IGrouping instance like below;
var ProcessAudList = collection.Where(x => x.Active == "Y").GroupBy(x => x.ProjectSeq).Select(x => x.OrderByDescending(a => a.ProcessSeq).FirstOrDefault()).ToList();
Hope this helps
You're most of the way there, but Max is the wrong term to use.
Each IGrouping is an IEnumerable (or IQueryable) sequence of its own, so you can use OrderBy and First clauses to get the answer you need:
var ProcessAudList = ProcessAudService
.FilterBy(x => x.Active == "Y")
.GroupBy(x => x.ProjectSeq)
.Select(grp => grp.OrderByDescending(x => x.ProcessSeq).First())
.ToList();
The Select clause will process each of the groups, order the groups descending by ProcessSeq and select the first one. For the data you provided this will select the rows with ProcessSeq equal to 12 and 14.
With this code you can get all max id in foreach
var res = from pa in ProcessAud
group Cm by pa.ProjectSeq into Cm1
select new
{
_max = Cm1.Max(x => x.ProcessSeq)
};
foreach (var item in res)
{
//item._max have biggest id in group
}
I have a dataset that i want to groupby to determine duplicate data.
Example i have a dataset that looks like this.
|id | Number | ContactID
1 1234 5
2 9873 6
3 1234 7
4 9873 6
Now i want to select data that has more than one occurrence of Number but only if the ContactID is not the same.
So basically return
| Number | Count |
1234 2
Any help would be appreciated using LINQ to EF, thanks.
Update:
All thanks to #DrCopyPaste, as he told me that I misunderstood your problem. Here is the correct solution:-
var result = from c in db.list
group c by c.Number into g
let count = g.GroupBy(x => x.ContactID).Where(x => x.Count() == 1).Count()
where count != 0
select new
{
Number = g.Key,
Count = count
};
Sample Fiddle.
This query avoids making a custom IEqualityComparer as if I remember correctly don't think they play well with EF.
var results = data.GroupBy(number => number.Number)
.Where(number => number.Count() > 1)
.Select(number => new
{
Number = number.Key,
Count = number.GroupBy(contactId => contactId.ContactId).Count(x => x.Count() == 1)
})
.Where(x => x.Count > 0).ToList();
Fiddle
It does an initial GroupBy to get all Numbers that are duplicated. It then selects a new type that contains the number and a second GroupBy that groups by ContactId then counts all groups with exactly one entry. Then it takes all results whose count is greater than zero.
Have not testing it against EF, but the query uses only standard Linq operators so EF shouldn't have any issues translating it.
Another way of doing this(using 1 level of grouping):
var results = data
.Where(x => data.Any(y => y.Id != x.Id && y.Number == x.Number && y.ContactId != x.ContactId))
.GroupBy(x => x.Number)
.Select(grp => new { Number = grp.Key, Count = grp.Count() })
.ToList();
Fiddle
i am very new with C# and MVC.
My Problem:
I have a list OF IDs
int[] mylist = {10, 23}
I try to query some data from DB
var result = db.tableName.Where(o => mylist.Any(y => y == o.item_ID && o.readed)).ToList();
This is what I get with the query:
item_ID Product_ID readed
277 1232 1
277 1233 1
277 1235 1
280 1235 1
What I need is:
item_ID Product_ID readed
277 1235 1
280 1235 1
If I change "any" to "all" i don't get any results, but I have definitely one item where the condition fits.
I think its more like make a query with id 277, then a query with 280 and then merge the list and return only where where "Product_ID" match.
Any ideas?
I assume that what you need is this:
var temp = db.tableName.Where(o => mylist.Any(y => y == o.item_ID && o.readed))
.ToList();
// Find the Product_id which appeared more than one time
// By the way, this assumes that there is at least one product_Id whihc has appeared more than one time
var neededProductID = temp.GroupBy(x => x.Product_ID)
.Where(x => x.Count() > 1)
.First()
.Key;
// Filter the result by neededProductID
var result = temp.Where(x => x.Product_ID == neededProductID).ToList();
Also, if there could be more tha one Product_ID which has apperaed more than one time, then you can consider this:
var neededProductID = temp.GroupBy(x => x.Product_ID)
.Where(x => x.Count() > 1)
.Select(x => x.Key)
.ToList();
var result = temp.Where(x => neededProductID.Any(y => y == x.Product_ID)).ToList();
By the way, you don't need All(). It tells you if all the elements in a collection match a certain condition.
You can use the following
var result = db.tableName.Where(o => mylist.conains(o.item_ID)
&& o.readed).ToList();
I have an array of objects with property Number inside them. I need to group them by values i.e. objects contain those sample values:
1 2 3 3 3 4 5 6 6 6 7 7
I have to group them like this:
listOfUniqe = {1,2,4,5}
listOfDuplicates1 = {3,3,3}
listOfDuplicates2 = {6,6,6}
listOfDuplicates3 = {7,7}
...
I tried to use distinct, with First(). But this distincts me first occurences and remove duplicates. I want to erase also first occurence of object if it had duplicates and move them to another list.
List<Reports> distinct = new List<Reports>;
distinct = ArrayOfObjects.GroupBy(p => p.Number).Select(g => g.First()).ToList();
Any ideas how I could do this?
To get groups with just one element use that:
distinct = ArrayOfObjects.GroupBy(p => p.Number)
.Where(g => g.Count() == 1)
.ToList();
And to get list of groups with more elements use that:
nonDistinct = ArrayOfObjects.GroupBy(p => p.Number)
.Where(g => g.Count() > 1)
.Select(g => g.ToList())
.ToList();
First group the items:
var groups = values.GroupBy(p => p.Number).ToList();
The unique ones are the ones with a group count of one:
var unique = groups.Where(g => g.Count() == 1).Select(g => g.Single()).ToList();
The ones with duplicates are the other ones:
var nonUnique = groups.Where(g => g.Count() > 1).ToList();