I need to get topic name and number of times (count) a given topic occurs.
Example:
Name: John
Topic: X, Y, Z => these are List<string>
Name: Bob
Topic: Y
Name: Suzy
Topic: Y, Z
Should generate output:
X: 1
Y: 3
Z: 2
I've tried this but it doesn't return correct result:
var result = from r in items
orderby r.Topic
group r by r.Topic
into grp
select new { key = grp.Key, cnt = grp.Count() };
You can flatten the contained collection with another from:
var result = from r in lineItems
from t in r.Topic // List<string>
group t by t into grp
orderby grp.Key
select new { key = grp.Key, cnt = grp.Count() };
I like to do this using SelectMany( to flatten the inner collection)
Just another way to do this
var result = items.SelectMany((w) => w.Topic)
.GroupBy((q) => q)
.Select((p) => new { Grp = p.Key, Cnt = p.Count() })
.OrderBy((g) => g.Cnt);
Related
I have a list in my code that I need to filter through and return specific rows based on two criteria. The List in question is a list of models from a database. There are two ID properties on each model, one is the ID from the data table and is unique, the other is an ID we use to identify groups and can repeat. We'll call them ID and GroupID. Basically, I want the resulting list to have only one of each GroupID, and it should be the one with the highest (numerically speaking) ID. For example:
Input:
List<MyModel> modelList = new List<MyModel>
modelList[0].ID = 1 modelList[0].GroupID = 5
modelList[1].ID = 2 modelList[1].GroupID = 5
modelList[2].ID = 3 modelList[2].GroupID = 6
modelList[3].ID = 4 modelList[3].GroupID = 6
Desired Output:
Models at indexes 1 and 3.
Using LINQ:
var items = (from model in modelList
group model by model.GroupID into modelGroup
select modelGroup.Max(i => i.ID)).ToList();
What you have to do here is first order the modelList by ID and then GroupBy the list items by GroupID, then pull the item with max Id value.
var result = modelList.OrderByDescending(x => x.ID).GroupBy(x => x.GroupID).Select(x => x.First());
the above query will give you the result.
This is your solution:
var myData = models.GroupBy(model => model.GroupId)
.Select(group => group.OrderByDescending(model => model.Id).First());
Or you could also do this:
var myData = models.GroupBy(model => model.GroupId)
.Select(group => group.First(model => model.Id == group.Max(model1 => model1.Id)));
For fun, here's a fiddle.
You can try to use GroupBy.
var q = modelList.GroupBy(x => x.GroupID, x => x,
(key, g) => new {
GroupID = key,
Id = g.Max(c => c.ID)
});
This should group all your elements by GroupId and select Max ID in one of that groups.
Try this code:
List<MyModel> modelList = new List<MyModel>();
modelList.Add(new MyModel());
modelList.Add(new MyModel());
modelList.Add(new MyModel());
modelList.Add(new MyModel());
modelList[0].ID = 1; modelList[0].GroupID = 5;
modelList[1].ID = 2; modelList[1].GroupID = 5;
modelList[2].ID = 3; modelList[2].GroupID = 6;
modelList[3].ID = 4; modelList[3].GroupID = 6;
var list = from ml in modelList group ml by ml.ID into r select new { ID = r.Key, MaxGroupID = r.Max() };
this might help you
modelList.GroupBy(model => model.GroupId, g => g.Id).Select(item => item.Max())
var newModelList = modelList.GroupBy(ml => ml.GroupID)
.Select(g => new MyModel
{
ID = g.OrderByDescending(x => x.ID).First().ID,
GroupID = g.Key
}).ToList();
Details
1) GroupBy then Select to get distinct items over GroupID.
2) First() after OrderByDescending to get highest ID.
3) new MyModel in Select is just to be explicit about the projection.
I wanted to sum the DayDifference based on studentId
List<Timeliness> studentData = (from redt in RoundEndDateTable.AsEnumerable()
join st in Activity on redt.Field<string>("strActivityName") equals st.ActivityName
orderby (DateTime.Parse(redt.ItemArray[1].ToString()) - DateTime.Parse(st.RewardType.ToString())) descending
select new Timeliness
{
DayDifference = int.Parse((DateTime.Parse(redt.ItemArray[1].ToString()) - DateTime.Parse(st.RewardType)).ToString().Split('.')[0]),
StudentId = st.AssociateId.ToString()
}).ToList();
I tried the below code
var groupedCustomerList = studentData
.GroupBy(u => u.StudentId)
.Select(grp => grp.ToList())
.ToList();
Not sure where to add the sum in the above codes
In the first query i am getting student id repeated
ex:
[0] - studentid:123 DayDifference:16
[1] - studentid:123 DayDifference:8
[2] - studentid:121 DayDifference:16
I need
[0] - studentid:123 DayDifference:24
[2] - studentid:121 DayDifference:16
This should create a collection of anonymous types, containing each "Key" (StudentId), and the sum of the "DayDifference" values for each StudentId:
var result =
studentData.GroupBy(u => u.StudentId)
.Select(grp => new { Id = grp.Key, TotalDiff = grp.Sum(x => x.DayDifference) })
.ToList();
I have a string array of names or could be a List of names which can have multiple duplicate names. What I want to do is to get a list of top 5 most duplicate names. Could someone tell me what's the best way to do this?
Array[0] = 'Mike'
Array[1] = 'Tim'
Array[2] = 'Debra'
Array[3] = 'Mike'
Array[4] = 'Steve'
Array[5] = 'Mike'
Array[6] = 'Amy'
Array[7] = 'Tim'
Array[8] = 'Debra'
Array[9] = 'Amy'
Output: Mike has 3
Tim has 2
Debra has 2
Steve has 1
Amy has 1
Here is how it can be done with grouping:
var result = from name in namesArray
group name by name into g
orderby g.Count() descending
select new { Name = g.Key, Count = g.Count() };
If you need just top 5 - call .Take(5) of that:
var result = (from name in namesArray
group name by name into g
orderby g.Count() descending
select new { Name = g.Key, Count = g.Count() }).Take(5);
The easiest way to do this is to use GroupBy.
var result = Array
.GroupBy(x => x)
.Select(x => new { Name = x.Key; Count = x.Count() })
.OrderByDescending(x => x.Count)
.Take(5);
Looks to me like you want to do something with Linq,
var results = from name in names
group name by name into nameGroup
let count = nameGroup.Count()
orderby count descending
take 5
select new {Value = name, Count = count};
After which you can format the contents of the results as you desire.
List<int> ListIdProducts = new List<int>();
var IdProductKey = from a in me.ProductKeywords where a.Keyword == item.Id select a;
foreach (var item2 in IdProductKey)
{
ListIdProducts.Add(item2.Product.Value);
}
Result is:
5
6
7
5
2
5
I need to get the following 5=3, 6=1, 7=1, 2=1
Use GroupBy LINQ method:
ListIdProducts
.GroupBy(i => i)
.Select(g => new { Value = g.Key, Count = g.Count() });
var query1 = from a in ListIdProducts
group a by new { a } into g
select new
{
item = g.Key,
itemcount = g.Count()
};
This a fairly standard group-by problem.
//untested
var IdProducts = from a in me.ProductKeywords
where a.Keyword == item.Id
group by a.Product.Value into g
select g.Count();
I would like a third column "items" with the values that are grouped.
var dic = new Dictionary<string, int>();
dic.Add("a", 1);
dic.Add("b", 1);
dic.Add("c", 2);
dic.Add("d", 3);
var dCounts =
(from i in dic
group i by i.Value into g
select new { g.Key, count = g.Count()});
var a = dCounts.Where(c => c.count>1 );
dCounts.Dump();
a.Dump();
This code results in:
Key Count
1 2
2 1
3 1
I would like these results:
Key Count Items
1 2 a, b
2 1 c
3 1 d
var dCounts =
(from i in dic
group i by i.Value into g
select new { g.Key, count = g.Count(), Items = string.Join(",", g.Select(kvp => kvp.Key)) });
Use string.Join(",", {array}), passing in your array of keys.
You can use:
var dCounts =
from i in dic
group i by i.Value into g
select new { g.Key, Count = g.Count(), Values = g };
The result created by grouping (value g) has a property Key that gives you the key, but it also implements IEnumerable<T> that allows you to access individual values in the group. If you return just g then you can iterate over all values using foreach or process them using LINQ.
Here is a simple dump function to demonstrate this:
foreach(var el in dCounts) {
Console.Write(" - {0}, count: {1}, values:", el.Key, el.Count);
foreach(var item in el.Values) Console.Write("{0}, ", item);
|
from i in dic
group i.Key by i.Value into g
select new
{
g.Key,
count = g.Count(),
items = string.Join(",", g.ToArray())
});