我有一个清单:
List<string> myList = new List<string>{ "dog", "cat", "dog", "bird" };
我希望输出列表:
"dog (1)", "cat", "dog (2)", "bird"
我已经查看了this个问题,但它只讨论重复计数,我的输出应该是重复索引。喜欢
duplicate (index)
我试过这段代码:
var q = list.GroupBy(x => x)
.Where(y => y.Count()>1)
.Select(g => new {Value = g.Key + "(" + g.Index + ")"})
但它似乎不起作用,因为:
如何在C#中执行此操作?有没有办法使用Linq?
答案 0 :(得分:2)
接受的解决方案有效,但当列表大小变大时效率极低。
您要做的是首先在高效的数据结构中获取所需的信息。你能实现一个类:
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)})";
}
这里的教训是:创建一个有用的帮助类,可以很好地解决一个问题,然后使用该帮助程序类使您的实际问题的解决方案更加优雅。你需要计算一些东西来解决问题吗? 制作一个反击类。
答案 1 :(得分:1)
执行此操作的一种方法是简单地创建一个新列表,其中包含多次出现的每个项目的附加文本。当我们找到这些项目时,我们可以使用计数器变量创建格式化的字符串,如果格式化字符串列表已包含该计数器,则递增计数器。
请注意,这是 NOT 一个表现良好的解决方案。这是我头脑中的第一件事。但这是一个开始的地方......
private static void Main()
{
var myList = new List<string> { "dog", "cat", "dog", "bird" };
var formattedItems = new List<string>();
foreach (var item in myList)
{
if (myList.Count(i => i == item) > 1)
{
int counter = 1;
while (formattedItems.Contains($"{item} ({counter})")) counter++;
formattedItems.Add($"{item} ({counter})");
}
else
{
formattedItems.Add(item);
}
}
Console.WriteLine(string.Join(", ", formattedItems));
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
<强>输出强>
答案 2 :(得分:1)
此解决方案在列表大小方面不是二次方,并且它在OP中首选修改列表。
任何有效的解决方案都会涉及预先通过,以便查找和计算重复项。
List<string> myList = new List<string>{ "dog", "cat", "dog", "bird" };
//map out a count of all the duplicate words in dictionary.
var counts = myList
.GroupBy(s => s)
.Where(p => p.Count() > 1)
.ToDictionary(p => p.Key, p => p.Count());
//modify the list, going backwards so we can take advantage of our counts.
for (int i = myList.Count - 1; i >= 0; i--)
{
string s = myList[i];
if (counts.ContainsKey(s))
{
//add the suffix and decrement the number of duplicates left to tag.
myList[i] += $" ({counts[s]--})";
}
}
答案 3 :(得分:1)