С#: удалить повторяющиеся значения из словаря?
Как создать словарь без дубликатов значений из словаря, который может иметь повторяющиеся значения?
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.???
Edit:
- Мне все равно, какой ключ сохранен.
- Есть ли что-то, использующее функцию Distinct()?
Ответы
Ответ 1
Что вы хотите делать с дубликатами? Если вы не возражаете против того, какой ключ вы потеряете, просто создайте еще один словарь:
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);
Ответ 2
Решение грубой силы будет выглядеть следующим образом
var result = dictionary
.GroupBy(kvp => kvp.Value)
.ToDictionary(grp => grp.First().Value, grp.Key)
предполагая, что вам действительно не нужен ключ, используемый для представления группы дубликатов, и приемлемо пересобирать словарь.
Ответ 3
Джон избил меня до решения .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);
}
}
Ответ 4
foreach (var key in mydict.Keys)
tempdict[mydict[key]] = key;
foreach (var value in tempdict.Keys)
uniquedict[tempdict[value]] = value;
Ответ 5
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);
}
Ответ 6
Вот как я это сделал:
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);
}
}
Ответ 7
В дополнение к ответу Jon Skeet, если ваше значение является объектом-участником, вы можете использовать:
var uniqueValues = myDict.GroupBy(pair => pair.Value.Property)
.Select(group => group.First())
.ToDictionary(pair => pair.Key, pair => pair.Value);
Таким образом вы удалите дубликат только по одному свойству объекта
Ответ 8
Просто примечание для тех, кто использует Revit API, это один из методов, который работает для меня при удалении повторяющихся элементов, когда вы не можете использовать say 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);
}
}