c# - 修改具有重复索引后缀的重复值(使用 Linq)

标签 c# linq

我有一个列表:

List<string> myList = new List<string>{ "dog", "cat", "dog", "bird" };

我希望输出是以下列表:

"dog (1)", "cat", "dog (2)", "bird"

我已经看过 this问题,但它只是在谈论计算重复项,我的输出应该是它的重复索引。喜欢 重复(索引)

我试过这段代码:

var q = list.GroupBy(x => x)
            .Where(y => y.Count()>1)
            .Select(g => new {Value = g.Key + "(" + g.Index + ")"})

但它似乎不起作用,因为:

  1. 需要返回我的所有列表\或者只修改现有列表。 (我的回答只返回重复的)
  2. 对于重复值需要添加基于其“重复索引”的前缀。

如何在 C# 中执行此操作?有没有办法使用 Linq?

最佳答案

公认的解决方案有效,但当列表的大小变大时效率极低。

您要做的是首先在高效的数据结构中获取您需要的信息。你能实现一个类吗:

sealed class Counter<T>
{
  public void Add(T item) { }
  public int Count(T item) { }
}

其中 Count 返回使用该项目调用 Add 的次数(可能为零)。 (提示:您可以使用 Dictionary<T, int> 来获得良好效果。)

好的。现在我们有了有用的助手,我们可以:

var c1 = new Counter<string>();
foreach(string item in myList)
  c1.Add(item);

太棒了。现在我们可以通过使用第二个计数器来构造我们的新列表:

var result = new List<String>();
var c2 = new Counter<String>();
foreach(string item in myList)
{
  c2.Add(item);
  if (c1.Count(item) == 1))
    result.Add(item);
  else
    result.Add($"{item} ({c2.Count(item)})");
}

我们完成了。或者,如果您想就地修改列表:

var c2 = new Counter<String>();
// It's a bad practice to mutate a list in a foreach, so
// we'll be sticklers and use a for.
for (int i = 0; i < myList.Count; i = i + 1)
{
  var item = myList[i];
  c2.Add(item);
  if (c1.Count(item) != 1))
    myList[i] = $"{item} ({c2.Count(item)})";
}

这里的教训是:创建一个非常好地解决一个问题的有用的帮助器类,然后使用该帮助器类使您的实际问题的解决方案更加优雅。您需要数数才能解决问题吗? 创建一个事物计数器类

关于c# - 修改具有重复索引后缀的重复值(使用 Linq),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48815000/

相关文章:

c# - 检测是否安装了 Office 365

c# - MVVM、XML 和主/详细方案

c# - SortedList 错误 : "Does not contain a definition for Select."

linq - LINQ-to-NHibernate FetchMany 的 where 子句?

c# - 两个流的条件配对 - 在响应式扩展中组合 If

c# - 按未选择的列排序

c# - 从非托管 C++ 调用托管 C# 函数(没有返回值)的无痛方式?

c# - 作为字符串的动态属性名称

c# - 解析完成前遇到流结尾

c# - 获取重复对象的列表,包括所有出现的 C#