【问题标题】:Extracting Key combinations when each Key shares an equal value [duplicate]当每个键共享相同的值时提取键组合[重复]
【发布时间】:2018-05-09 21:46:09
【问题描述】:

当每个键共享一个值时,我正在尝试生成一个字符串键组合列表,下面是我的代码的摘录

var keyCombos = new List<List<string>>();
var dict = new Dictionary<string, List<int>>();
dict.Add("A", new List<int>() { 1, 2, 3 });
dict.Add("B", new List<int>() { 1, 2, 3, 4 });
dict.Add("C", new List<int>() { 1, 4, 5 });

上面是一个字典,其中包含一个字符串键和一个整数列表作为其值,keyCombos 列表将保存共享整数列表值的所有键组合,keyCombos 的预期输出将低于

["A","B","C"] //1 is common
["A","B"] //1,2,3 are common
["B","C"] //1,4 are common
["C"] //5

组合的顺序并不重要,到目前为止,我的代码使用各种 foreach 循环,我只能组合 2 个键,而不是 1 或 3。

foreach(var k1 in dict.Keys)
            {
                List<int> a1 = dict[k1];
                foreach (var k2 in dict.Keys)
                {
                    if (k1 != k2)
                    {
                        List<int> a2 = dict[k2];

                        if(a1.Intersect(a2).Count()>0)
                        {
                            var matches = false;
                            foreach(var combo in keyCombos)
                            {
                                if ((combo.Contains(k1)) && (combo.Contains(k2)))
                                {
                                    matches = true;
                                }
                            }
                            if (!matches)
                            {
                                keyCombos.Add(new List<string>() { k1, k2 });
                            }
                        }
                        else
                        {
                            keyCombos.Add(new List<string>() { k1 });
                        }
                    }                    
                }
            }

【问题讨论】:

  • 您应该添加您当前的代码various foreach loops
  • 我已经更新了

标签: c# list dictionary


【解决方案1】:

使用 linq 你可以这样做

var enumarable = dict.SelectMany(g => g.Value.Select(k => new { Key = g.Key, Value = k}
));
var result = enumarable.GroupBy(g => g.Value, (key, group) => group.Select(g => g.Key).ToList());
keyCombos = result.Distinct(AnonymousComparer.Create((List<string> mc) => string.Join(";", mc))).ToList();

AnonymousComparer 是用于创建IEqualityComparer 的类。它来自 AnonymousComparernuget 包。

还是这样

keyCombos = dict.SelectMany(g => g.Value.Select(k => new { Key = g.Key, Value = k })).GroupBy(g => g.Value, (key, group) => group.Select(g => g.Key).ToList()).Distinct(AnonymousComparer.Create((List<string> mc) => string.Join(";", mc))).ToList();

首先,使用SelectMany,我们从字典中的值中排除列表,并获取所有具有重复键的键值对。
之后,我们只需按值对这个新集合进行分组,然后从组中选择键。最后,我们按值选择唯一组。

【讨论】:

  • 谢谢,有没有办法确保一个不同的列表,我已经测试了这段代码,一个包含 ["A","B"] 的列表出现了两次
  • @chillydk147,我已经编辑了答案。
  • 太好了,非常感谢
【解决方案2】:

我只是想澄清一下,您想返回所有在传递的“键”之间“共同/交集”的元素,对吧?

在 [“A”, “B”] 的情况下,不应该常见 1,2,3 而不是只有 2,3。如果是这样,请在问题陈述中更新。

在 [“C”] 的情况下,不应该有一个共同点,因为只有一个键。对吗?

如果是,那么您应该尝试以下方法:

    public List<int> FindIntersection(string[] keys, Dictionary<string, List<int>> dict)
    {
        if(keys.Length <= 1)
        {
            return null;
        }

        HashSet<int> commonElements = new HashSet<int>();
        dict[keys[0]].ForEach(x => commonElements.Add(x));

        for(int i = 1; i < keys.Length; i++)
        {
            commonElements.IntersectWith(dict[keys[i]]);
        }

        return commonElements.ToList();
    }

【讨论】:

  • 问题已更新
  • 太好了,谢谢!我希望我的简单解决方案对您有用。如果你想让我也解释一下,请告诉我。
【解决方案3】:

我相信最简单的方法是首先从字典中获取不同的整数,然后遍历它们并使用 linq 获取该整数在列表中的键。喜欢:

var distinctKeyCombos = dict.SelectMany(x => x.Value).Distinct();

 foreach(var i in distinctKeyCombos)
 {
     var keys = dict.Where(p => p.Value.Contains(i)).Select(p => p.Key);
 }

【讨论】:

    【解决方案4】:

    您可以在 LINQ 中使用 SelectMany 和 GroupBy 来完成:

        var pivot = dict.SelectMany(kv => kv.Value.Select(v => new {v, kv.Key}))
            .GroupBy(x => x.v);
    

    组的键是 int 值,其内容是包含值和字母的匿名类型。

    它首先将每个字母与 int 值配对(您也可以在此处使用 System.ValueTuple 代替匿名类型)。然后,它将列表列表扁平化为一个列表,最后按 int 值对它们进行分组。

    与其将值存储在字典中,不如将它们存储为简单的对(“A”,1),...然后您可以轻松地以任何一种方式检索它们:按字母分组或按整数分组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-06
      • 1970-01-01
      • 2018-12-05
      • 1970-01-01
      相关资源
      最近更新 更多