In C #, how do I concatenate strings and their frequency with the resulting string?
I know we can find duplicate elements like this:
var dublicateItems = itemStrings.GroupBy(x => x)
.Where(x => x.Count() > 1)
.ToDictionary(g => g.Key, g => g.Count());
And different elements like this:
var distinctItems = itemStrings.Distinct();
But how to combine it with the following list of strings:
input: a, b, b, c, d, d, d, d
output: a, b (2 times), c, d (4 times)
source to share
You are almost there:
var duplicateItems =
itemStrings
.GroupBy(i => i)
.Select(i => new { Key = i.Key, Count = i.Count() })
.Select(i => i.Key + (i.Count > 1 ? " (" + i.Count + " times)" : string.Empty));
If you want the result to be comma separated, you can do the following:
var result = string.Join(", ", duplicateItems);
source to share
You already have a solution with the first approach, remove Where
var itemCounts = itemStrings.GroupBy(x => x)
.ToDictionary(g => g.Key, g => g.Count());
string result = String.Join(", ",
itemCounts.Select(kv => kv.Value > 1
? string.Format("{0} ({1} times)", kv.Key, kv.Value)
: kv.Key));
Another approach uses Enumerable.ToLookup
instead GroupBy
:
var itemLookup = itemStrings.ToLookup(x => x);
string result = String.Join(", ",
itemLookup.Select(grp => grp.Count() > 1
? string.Format("{0} ({1} times)", grp.Key, grp.Count())
: grp.Key));
source to share
With something like:
string[] itemStrings = new[] { "a", "b", "b", "c", "d", "d", "d", "d" };
string[] duplicateItems = (from x in itemStrings.OrderBy(x => x).GroupBy(x => x)
let cnt = x.Count()
select cnt == 1 ?
x.Key :
string.Format("{0} ({1} times)", x.Key, cnt)
).ToArray();
I added OrderBy()
because your list seems to be ordered and I complicated it a bit for caching x.Count()
( let cnt = x.Count()
).
If you need one big line, you can
string joined = string.Join(",", duplicateItems);
source to share