在字典中查找重复列表并打印重复列表的键
Finding duplicate lists in dictionary and print Key of the duplicated list
如果有完全匹配的值列表,我有兴趣在字典中查找键
下面是一个字典,其中有与 class 关联的学生列表。
var studentsInClass = new Dictionary<string, List<string>>();
studentsInClass.Add("Maths", new List<string> { "James", "Bob", "Sophia" });
studentsInClass.Add("English", new List<string> { "James", "Bob", "Sophia", "Mel" });
studentsInClass.Add("History", new List<string> { "Hannah" });
studentsInClass.Add("Geography", new List<string> { "Paul", "Zack" });
studentsInClass.Add("Art", new List<string> { "Paul", "Zack" });
例如,我希望将 classes/keys 地理 和 艺术 视为 保罗 和 Zack(而且只有这两个)在这两个 class 中。 James、Bob 和 Sophia 都在 Math English,Mel 是 English,所以不是完全匹配。
我在这里关注了一个类似的问题Finding duplicate values in dictionary and print Key of the duplicate element
但我认为这不适用于列表或引用类型
您可以按通过连接字典中的列表项创建的字符串进行分组。这样,您就可以避免比较两个具有相同项目但指向不同引用的列表的问题。
var groups = studentsInClass.GroupBy(x => string.Join("", x.Value)).Where(x => x.Count() > 1);
在这里,如果这些组有多个项目,则对这些组进行分组和过滤,在您的示例中为地理和艺术。
在线演示:https://dotnetfiddle.net/Up72sw
注意:上面的代码会考虑学生的顺序。如果 Geography 是“Zack”、“Paul”,它不会将其识别为相同的。如果您想忽略商品的顺序,请在加入它们之前对您的商品进行排序:
var groups = studentsInClass.GroupBy(x => string.Join("", x.Value.OrderBy(y => y))).Where(x => x.Count() > 1);
Linq 可以使这个示例变得更好一些,但由于我猜这是入门课程的练习,所以我用循环完成了它。
var studentsInClass = new Dictionary<string, List<string>>();
studentsInClass.Add("Maths", new List<string> { "James", "Bob", "Sophia" });
studentsInClass.Add("English", new List<string> { "James", "Bob", "Sophia", "Mel" });
studentsInClass.Add("History", new List<string> { "Hannah" });
studentsInClass.Add("Geography", new List<string> { "Paul", "Zack" });
studentsInClass.Add("Art", new List<string> { "Paul", "Zack" });
var identicalClasses = new Dictionary<string, List<string>>();
/*iterate all key-value pairs in the just created dictionary*/
foreach (KeyValuePair<string, List<string>> entry in studentsInClass)
{
foreach (KeyValuePair<string, List<string>> entry2 in studentsInClass)
{
/* first we check if we're verifying a key that isn't the entry key itself.
* Secondly, we check if the list contains all elements in the second list.
* Finally, we make sure the lists are the same size.
*/
if (entry.Key != entry2.Key && entry.Value.All(entry2.Value.Contains) && entry.Value.Count == entry2.Value.Count) //If order matters, you can use entry.Value.SequenceEqual(entry2.Value)
{
/*add the key-value pair to a dict which we can use somewhere else.*/
identicalClasses.Add(entry.Key, entry.Value);
//Just to show the keys we've added to our identicalClasses list
Console.WriteLine("key = " + entry.Key);
//We need to break since we don't want to list the key multiple times should there be more than 2 identical classes.
break;
}
}
}
如果顺序很重要,那么您可以利用 Enumerable.SequenceEqual。
我能想到的最简单的解决方案:
foreach(var lhs in studentsInClass)
foreach(var rhs in studentsInClass)
{
if(lhs.Key == rhs.Key) continue;
if(Enumerable.SequenceEqual(lhs.Value, rhs.Value))
Console.WriteLine(lhs.Key + " + " + rhs.Key);
}
这将打印:
Geography + Art
Art + Geography
如果有完全匹配的值列表,我有兴趣在字典中查找键
下面是一个字典,其中有与 class 关联的学生列表。
var studentsInClass = new Dictionary<string, List<string>>();
studentsInClass.Add("Maths", new List<string> { "James", "Bob", "Sophia" });
studentsInClass.Add("English", new List<string> { "James", "Bob", "Sophia", "Mel" });
studentsInClass.Add("History", new List<string> { "Hannah" });
studentsInClass.Add("Geography", new List<string> { "Paul", "Zack" });
studentsInClass.Add("Art", new List<string> { "Paul", "Zack" });
例如,我希望将 classes/keys 地理 和 艺术 视为 保罗 和 Zack(而且只有这两个)在这两个 class 中。 James、Bob 和 Sophia 都在 Math English,Mel 是 English,所以不是完全匹配。
我在这里关注了一个类似的问题Finding duplicate values in dictionary and print Key of the duplicate element
但我认为这不适用于列表或引用类型
您可以按通过连接字典中的列表项创建的字符串进行分组。这样,您就可以避免比较两个具有相同项目但指向不同引用的列表的问题。
var groups = studentsInClass.GroupBy(x => string.Join("", x.Value)).Where(x => x.Count() > 1);
在这里,如果这些组有多个项目,则对这些组进行分组和过滤,在您的示例中为地理和艺术。
在线演示:https://dotnetfiddle.net/Up72sw
注意:上面的代码会考虑学生的顺序。如果 Geography 是“Zack”、“Paul”,它不会将其识别为相同的。如果您想忽略商品的顺序,请在加入它们之前对您的商品进行排序:
var groups = studentsInClass.GroupBy(x => string.Join("", x.Value.OrderBy(y => y))).Where(x => x.Count() > 1);
Linq 可以使这个示例变得更好一些,但由于我猜这是入门课程的练习,所以我用循环完成了它。
var studentsInClass = new Dictionary<string, List<string>>();
studentsInClass.Add("Maths", new List<string> { "James", "Bob", "Sophia" });
studentsInClass.Add("English", new List<string> { "James", "Bob", "Sophia", "Mel" });
studentsInClass.Add("History", new List<string> { "Hannah" });
studentsInClass.Add("Geography", new List<string> { "Paul", "Zack" });
studentsInClass.Add("Art", new List<string> { "Paul", "Zack" });
var identicalClasses = new Dictionary<string, List<string>>();
/*iterate all key-value pairs in the just created dictionary*/
foreach (KeyValuePair<string, List<string>> entry in studentsInClass)
{
foreach (KeyValuePair<string, List<string>> entry2 in studentsInClass)
{
/* first we check if we're verifying a key that isn't the entry key itself.
* Secondly, we check if the list contains all elements in the second list.
* Finally, we make sure the lists are the same size.
*/
if (entry.Key != entry2.Key && entry.Value.All(entry2.Value.Contains) && entry.Value.Count == entry2.Value.Count) //If order matters, you can use entry.Value.SequenceEqual(entry2.Value)
{
/*add the key-value pair to a dict which we can use somewhere else.*/
identicalClasses.Add(entry.Key, entry.Value);
//Just to show the keys we've added to our identicalClasses list
Console.WriteLine("key = " + entry.Key);
//We need to break since we don't want to list the key multiple times should there be more than 2 identical classes.
break;
}
}
}
如果顺序很重要,那么您可以利用 Enumerable.SequenceEqual。
我能想到的最简单的解决方案:
foreach(var lhs in studentsInClass)
foreach(var rhs in studentsInClass)
{
if(lhs.Key == rhs.Key) continue;
if(Enumerable.SequenceEqual(lhs.Value, rhs.Value))
Console.WriteLine(lhs.Key + " + " + rhs.Key);
}
这将打印:
Geography + Art
Art + Geography