我需要一个唯一值列表。但可能是,列表中的值存在两次或更多次。 如果发生这种情况,我必须重命名该值,但重命名的值也可以在列表中。
可以使用LINQ查询重命名值,这样我就不需要子查询了吗?
示例1: 的前: “一个”,“一个”,“两个”,“两个”,“三个” 的后: “一个”,“一个”,“两个”,“两个”,“三个”
示例2: 的前: “一一一_” 的后: “一个”,“一个”,“一个__”
第3个“one”有2个下划线,因为第2个“one”被重命名为“one _”。
非常感谢您的想法...
答案 0 :(得分:12)
我认为这不应该只使用linq查询来完成。如果我是你,我会使用HashSet并创建一个函数。像这样:
IEnumerable<String> GetUnique(IEnumerable<String> list) {
HashSet<String> itms = new HashSet<String>();
foreach(string itm in list) {
string itr = itm;
while(itms.Contains(itr)) {
itr = itr + "_";
}
itms.Add(itr);
yield return itr;
}
}
这可以作为扩展方法,所以你可以这样称呼它:myList.GetUnique();
(或类似的东西)
修正了更改迭代器变量的错误。
答案 1 :(得分:2)
我会创建一个像这样的新扩展方法:
public static IEnumerable<string> Uniquifier(this IEnumerable<string> values)
{
if (values == null) throw new ArgumentNullException("values");
var unique = new HashSet<string>();
foreach(var item in values)
{
var newItem = item;
while(unique.Contains(newItem))
{
newItem += '_';
}
unique.Add(newItem);
yield return newItem;
}
}
这将采用任何字符串序列,并创建一个HashSet - 非常快,O(1) - 的值。如果该值已存在,则会附加“_”并再次尝试。一旦它有一个唯一的,就返回它。
答案 2 :(得分:1)
使用扩展方法:
public static class EnumerableExtensions
{
public static IEnumerable<string> Uniquify(this IEnumerable<string> enumerable, string suffix)
{
HashSet<string> prevItems = new HashSet<string>();
foreach(var item in enumerable)
{
var temp = item;
while(prevItems.Contains(temp))
{
temp += suffix;
}
prevItems.Add(temp);
yield return temp;
}
}
}
用法:
var test1 = new[] {"one","one","two","two","three"};
Console.WriteLine(String.Join(",",test1.Uniquify("_")));
实例:http://rextester.com/rundotnet?code=BYFVK87508
修改:使用while循环现在支持以前根据以下评论不支持的所有情况。