当每个密钥共享一个相等的值时,提取密钥组合

时间:2018-05-09 12:19:29

标签: c# list dictionary

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

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 });

上面是一个字典,其中包含一个字符串Key和一个整数列表作为其值,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 });
                        }
                    }                    
                }
            }

4 个答案:

答案 0 :(得分:2)

使用linq你可以这样做

AnonymousComparer

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(); 是用于创建IEqualityComparer的类。它来自 AnonymousComparer nuget包。

或者就是这样

SelectMany

首先,使用 $(function () { $("#datepicker").datepicker({ onSelect: function () { $('#sched_macs_button').show(300); }, dateFormat: 'yy-mm-dd', changeMonth: true, beforeShowDay: $.datepicker.noWeekends, numberOfMonths: 1, minDate: dateToday }); }); 我们从字典中的值中排除列表,并获取具有重复键的所有键值对。
之后我们只按值组合这个新集合并从组中选择键。最后,我们按值选择唯一的组。

答案 1 :(得分: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();
    }

答案 2 :(得分:1)

我认为最简单的方法是首先从字典中获取不同的整数,然后遍历它们并使用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);
 }

答案 3 :(得分:0)

您可以使用SelectMany和GroupBy在LINQ中执行此操作:

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

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

首先将每个字母与一对中的int值配对(你也可以在这里使用System.ValueTuple而不是匿名类型)。然后它将列表列表展平为单个列表,最后按int值对它们进行分组。

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