在C#中,如何将字符串及其频率合并为一个结果字符串?

3

我知道我们可以这样查找重复的项目:

var dublicateItems = itemStrings.GroupBy(x => x)
                                .Where(x => x.Count() > 1)
                                .ToDictionary(g => g.Key, g => g.Count());

还有像这样不同的项目:

var distinctItems = itemStrings.Distinct();

但如何将其与以下字符串列表组合:

输入:a,b,b,c,d,d,d,d

输出:a,b(2次),c,d(4次)


什么是项目字符串?itemStrings.GroupBy(x => x)听起来像是你想要的。 - Sayse
4
".ToDictionary(...).ToList()" 让我感到非常痛苦。我将为您进行翻译,使之更通俗易懂,但不改变原意。 - Rawling
@Rawling 抱歉,只是编辑它们。 - Anatoly
@Anatoly 呵呵,抱歉,我那样说并不是很有建设性。这只是我从未见过的东西! - Rawling
3个回答

5
你已经接近成功了:
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));

如果您想要将结果作为逗号分隔的字符串返回,您可以这样做:
var result = string.Join(", ", duplicateItems);

4
你离成功不远了,只是出现了些许的间距和逗号问题。 - Rawling
我会移除最后的 .ToList(),并将 = 右侧整个部分用 string.Join(" ", ...) 包裹起来,以满足他的需求。 - krillgar
@krillgar 嗯,不清楚 OP 是想要一个逗号分隔的字符串还是一个字符串列表。但我会添加这个选项,好吧。 - Luaan
1
@Rawling Duh,我是个傻瓜:D 输出中的尾随空格不容易看到... :D - Luaan
@krillgar 你说的标题是正确的。不过,我不会从输出格式中得出任何结论 - 毕竟,尽管输入应该是一个字符串数组,但 OP 也以同样的方式格式化了输入。这就让我感到困惑了 :) - Luaan
显示剩余3条评论

2

使用第一种方法,去掉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)); 

另一种方法是使用Enumerable.ToLookup而不是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)); 

1

类似于以下内容:

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

我已经添加了一个`OrderBy()`,因为你的列表似乎是有序的,并且我为了缓存`x.Count()`而过于复杂化了它(使用了`let cnt = x.Count()`)。
如果您想要一个大字符串,您可以这样做。
string joined = string.Join(",", duplicateItems);

1
使用 let 更好,你说得对。我没有真正充分利用它的价值 :)) - Luaan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接