我有一个列表:
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 + ")"})
但它似乎不起作用,因为:
- 需要返回我的所有列表\或者只修改现有列表。 (我的回答只返回重复的)
- 对于重复值需要添加基于其“重复索引”的前缀。
如何在 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/