Get grouped comma separated values with linq - c#

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())
});

Related

Get count of same value on table

I have this class where the query must result in this list a property.
This property must check on table how many duplicated exists.
This code works, but its very slow. can you help me ?
var lst = _uow.Repository.GetAll();
var query =
from p in lst
select new GetRfqResponse
{
ID = p.ID,
//bad performance
Count = lst.Where(x => x.Property == p.Property).AsQueryable().Count(),
//
};
Counting in a queryable list can be easily achieved using the Count() function:
// Find duplicated names
var byName = from s in studentList
group s by s.StudentName into g
select new { Name = g.Key, Count = g.Count() };
Check this fiddle to see it running.
Below is for InMemory
GroupBy should come to help.
var propertyGroupedList = list.GroupBy(l=>l.Property);
var query = list.Select(l => new GetRfqResponse{
Id = l.Id,
Count = propertyGroupedList.First(g=> g.Key == l.Property).Count()
});
Or you can create a dictionary with key as "Property" and value as count, then you will have to loop just once to store the count.
This allows you to get count in constant time
Dictionary<string, int> map = new Dictionary<string, int>();
foreach (var item in lst)
{
if (!map.ContainsKey(lst.Property))
{
map.Add(item.Property, 1);
}
else
map[item.Property]++;
}
var z = lst.Select(l => new GetRfqResponse{
Id = l.ID,
Count = map[l.Property]
});

Linq group by and get count of occurence

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);

How to count duplicate items in an array

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.

how to get the number of repetitions from List<int>

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();

Counting words in a collection using LINQ

I have a StringCollection object with 5 words in them. 3 of them are duplicate words. I am trying to create a LINQ query that will count how many unique words are in the collection and output them to to the console. So, for example, if my StringCollection has 'House', 'Car', 'House','Dog', 'Cat', then it should output like this:
House --> 2
Car --> 1
Dog --> 1
Cat --> 1
Any ideas on how to create a LINQ query to do this?
Try the following
var res = from word in col.Cast<string>()
group word by word into g
select new { Word = g.Key, Count = g.Count() };
var xs = new StringCollection { "House", "Car", "House", "Dog", "Cat" };
foreach (var g in xs.Cast<string>()
.GroupBy(x => x, StringComparer.CurrentCultureIgnoreCase))
{
Console.WriteLine("{0}: {1}", g.Key, g.Count());
}
Given that you are using StringCollection and want to ignore case, you'll need to use Enumerable.GroupBy with Enumerable.Cast:
var results = collection.Cast<string>.GroupBy(
i => i,
(word, words) => new { Word = word, Count = words.Count() },
StringComparer.CurrentCultureIgnoreCase
);
foreach(var wordPair in results)
Console.WriteLine("Word: \"{0}\" - Count: {1}", wordPair.Word, wordPair.Count);
To build a single string value result...
var stringCollection = new[] { "House", "Car", "house", "Dog", "Cat" };
var result = stringCollection.Cast<string>().GroupBy(
k => k,
StringComparer.InvariantCultureIgnoreCase)
.Select(v => v.Key + " -->" + v.Count())
.Aggregate((l,r)=>l+" " + r);
//result = "House -->2 Car -->1 Dog -->1 Cat -->1"
To put each value on a different line...
var stringCollection = new[] { "House", "Car", "house", "Dog", "Cat" };
var result = stringCollection.Cast<string>().GroupBy(
k => k,
StringComparer.InvariantCultureIgnoreCase);
foreach (var value in result)
Console.WriteLine("{0} --> {1}", value.Key, value.Count());
foreach(var g in input.GroupBy(i => i.ToLower()).Select(i => new {Word = i.Key, Count = i.Count()})
{
Console.WriteLine(string.Format("{0} -> {1}", g.Word, g.Count));
}
It should be as simple as:
Console.WriteLine(stringCollection.Distinct().Count());
var query =
from s in Collection
group s by s.Description into g
select new {word = g.Key, num = g.Count()};

Categories

Resources