C#: 从字典中删除重复的值?

23

我该如何从可能包含重复值的字典中创建一个没有重复值的字典?

IDictionary<string, string> myDict = new Dictionary<string, string>();

myDict.Add("1", "blue");
myDict.Add("2", "blue");
myDict.Add("3", "red");
myDict.Add("4", "green");


uniqueValueDict = myDict.???

编辑:

- 我不在乎保留哪个键。 - 有没有使用 Distinct() 操作的方法?


6
你想保留哪个键?是“1”、“2”还是都不要? - dtb
我认为您需要提供有关唯一化函数行为的更多信息。对于蓝色,它应该保留哪个键,1还是2? - Tesserex
http://www.codeproject.com/KB/linq/Unique.aspx - Danny Varod
8个回答

51

你想如何处理这些重复的键?如果你不介意失去哪一个键,可以像下面这样建立另一个字典:

IDictionary<string, string> myDict = new Dictionary<string, string>();

myDict.Add("1", "blue");
myDict.Add("2", "blue");
myDict.Add("3", "red");
myDict.Add("4", "green");

HashSet<string> knownValues = new HashSet<string>();
Dictionary<string, string> uniqueValues = new Dictionary<string, string>();

foreach (var pair in myDict)
{
    if (knownValues.Add(pair.Value))
    {
        uniqueValues.Add(pair.Key, pair.Value);
    }
}

假设您正在使用 .NET 3.5。如果您需要 .NET 2.0 的解决方案,请告诉我。

这是一个基于 LINQ 的解决方案,我认为非常简洁...

var uniqueValues = myDict.GroupBy(pair => pair.Value)
                         .Select(group => group.First())
                         .ToDictionary(pair => pair.Key, pair => pair.Value);

12
他并不知道当计数器达到10万后会重新从0开始,ruuhaha。 - SwDevMan81
谢谢。Linq解决方案正是我在寻找的。不知道你是否可以使用Distinct扩展方法? - User
@User:我认为Distinct在这种情况下不会有帮助...但是MoreLINQ中的DistinctBy会有用。 - Jon Skeet
LINQ方法并不适用于所有情况。有些字典集不允许您调用.GroupBy()方法。 - Mitchell Skurnik
@Jon,是的...我忘记引用System.Linq了。我应该知道得更好。谢谢你的帮助! - Mitchell Skurnik
显示剩余3条评论

9
粗暴的解决方案可能是以下内容:
var result = dictionary
    .GroupBy(kvp => kvp.Value)
    .ToDictionary(grp => grp.First().Value, grp.Key)

假设您并不关心用于表示重复组的键,并且重新构建字典是可以接受的。

我尝试想象类似于linq的解决方案,但手边没有VS。+1 来支持这种方法的实现;-) - queen3
因为在 First() 调用后我错过了 .Value,所以没有编译通过,但是现在已经修复了。 - Daniel Brückner
1
这对我没用。它创建了一个字典,其中“value”既是键又是值。 - User
这将生成一个以值作为键和值的字典! :-( - Peter Albert

3

Jon已经提供了.NET 3.5的解决方案,但如果你需要.NET 2.0的解决方案,这个应该可以使用:

        List<string> vals = new List<string>();
        Dictionary<string, string> newDict = new Dictionary<string, string>();
        foreach (KeyValuePair<string, string> item in myDict)
        {
            if (!vals.Contains(item.Value))
            {
                newDict.Add(item.Key, item.Value);
                vals.Add(item.Value);
            }
        }

1
foreach (var key in mydict.Keys)
  tempdict[mydict[key]] = key;
foreach (var value in tempdict.Keys)
  uniquedict[tempdict[value]] = value;

1
Dictionary<string, string> test = new Dictionary<string,string>();
test.Add("1", "blue");
test.Add("2", "blue");
test.Add("3", "green");
test.Add("4", "red");
Dictionary<string, string> test2 = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> entry in test)
{
    if (!test2.ContainsValue(entry.Value))
        test2.Add(entry.Key, entry.Value);
}

1
这是我做的方式:

                dictionary.add(control, "string1");
                dictionary.add(control, "string1");
                dictionary.add(control, "string2");
              int x = 0;
        for (int i = 0; i < dictionary.Count; i++)
        {         
            if (dictionary.ElementAt(i).Value == valu)
            {
                x++;
            }
            if (x > 1)
            {
                dictionary.Remove(control);
            }
        }

0
除了 Jon Skeet 的回答之外,如果您的值是一个内部对象,您可以使用以下方法:
var uniqueValues = myDict.GroupBy(pair => pair.Value.Property)
                     .Select(group => group.First())
                     .ToDictionary(pair => pair.Key, pair => pair.Value);

这样你只会移除对象的一个属性的重复项


0
对于使用 Revit API 的人,这里有一个方法可以帮助你移除重复元素,特别是当你无法使用 wallType 作为对象类型时,需要利用原始元素。它非常好用。
  //Add Pair.value to known values HashSet
                 HashSet<string> knownValues = new HashSet<string>();

                Dictionary<Wall, string> uniqueValues = new Dictionary<Wall, string>();

                 foreach (var pair in wall_Dict)
                 {
                     if (knownValues.Add(pair.Value))
                     {
                         uniqueValues.Add(pair.Key, pair.Value);
                     }
                 }

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