c# linq组合了两个字典

本文关键字:两个 字典 linq 组合 | 更新日期: 2023-09-27 18:06:22

我有两个Dictionary<string, Item>Item有一个公有属性int Level

我想结合这两个字典,其中键是唯一的,并且我想能够指定两个字典的级别。

之类的
dictionary 1 =所有级别为<10字典2 =所有物品等级<20.组合字典2和1(其中Value。水平& lt;10)如果Key是唯一的,且Value。水平& lt;20 之前

我可以很容易地用foreach循环做到这一点。我也可以用多个linq查询做到这一点。然而,我似乎无法弄清楚如何使这一个单一的linq查询。

编辑-根据您的要求,John这里是foreach

的代码
Dictionary<string, Dictionary<string, Item>> itemDictionary = new Dictionary<string, Dictionary<string, Item>>();
Dictionary<string, Item> items = new Dictionary<string,Item>();
            if (itemDictionary.ContainsKey(comboBox.Text))
            {
                foreach (KeyValuePair<string, Item> kvp in itemDictionary[comboBox.Text])
                {
                    if (!items.ContainsKey(kvp.Key) && kvp.Value.Level <= int.Parse(textBox.Text))
                        items.Add(kvp.Key, kvp.Value);
                }
            }
            if (itemDictionary.ContainsKey(comboBox1.Text))
            {
                foreach (KeyValuePair<string, Spell> kvp in itemDictionary[comboBox1.Text])
                {
                    if (!items.ContainsKey(kvp.Key) && kvp.Value.Level <= int.Parse(textBox1.Text))
                        items.Add(kvp.Key, kvp.Value);
                }
            }
            var query = from s in items
                        orderby s.Value.Level
                        select s;
            foreach (var i in query)
               listBox.Items.Add(string.Format("{0} {1}", i.Value.Level, i.Key));

c# linq组合了两个字典

如果您可以轻松地在foreach循环中执行您想要的操作,那么您已经编写了代码。这告诉我,foreach代码可能比一个复杂的LINQ查询更容易读,更容易维护。

这听起来像是保留foreach循环代码的完美案例。

好了,这段代码明确了您想要完成的任务。因此,最终结果应该是由两个字典中满足指定级别的项组成的字典。如果一个项在两个字典中都存在,则首选第一个字典中的项。虽然可以在单个Linq查询中完成此任务,但最终会重复一些工作。这是我想出来的,如果你想尝试一下,它可以在LinqPad上运行。

var itemsOne = new[] {
    new { Name = "A", Level = 1 },
    new { Name = "B", Level = 2 },
    new { Name = "C", Level = 3 },
    new { Name = "D", Level = 4 }
}.ToDictionary(i => i.Name, i => i);
var itemsTwo = new[] {
    new { Name = "C", Level = 10 },
    new { Name = "D", Level = 20 },
    new { Name = "E", Level = 30 },
    new { Name = "F", Level = 40 }
}.ToDictionary(i => i.Name, i => i);
var itemsOneLevel = 3;
var itemsTwoLevel = 30;
var validFromItemsOne = (from item in itemsOne
                         where item.Value.Level <= itemsOneLevel
                         select item).ToDictionary(i => i.Key, i => i.Value);
var validFromItemsTwo = from item in itemsTwo
                        where item.Value.Level <= itemsTwoLevel
                            && !validFromItemsOne.ContainsKey(item.Key)
                        select item;
var items = validFromItemsOne
    .Concat(validFromItemsTwo)
    .ToDictionary(i => i.Key, i => i.Value);

如果我理解正确的话:您希望记录同时存在于两个字典中。无论如何,我的例子可以根据你的特殊需要量身定做。

Dictionary<string, string> d1 = new Dictionary<string, string>(), d2 = new Dictionary<string, string>();
        var merged = d1
            .Join(d2, d1key => d1key.Key, d2key => d2key.Key,
                (i1, i2) => new { Key = i1.Key, Value1 = i1.Value, Value2 = i2.Value })
            .ToDictionary(t => t.Key);

Merged将只包含存在于两个字典中的项,并且能够获取每个项的数据,例如Merged ["key"]。Value1和合并的["key"]。Value2例如,我使用了匿名类型(new{})。因此,您将只能在同一个方法中访问Value1和Value2,或者在绑定中访问,因为它们无论如何都是动态的。在其他情况下,您应该创建一个类型来存储合并后的结果。

这是一个扩展,我认为将适用于这种情况。

public static class Extensions
{
    public static IDictionary<TKey, TValue> Combine<TKey, TValue>(
        this IDictionary<TKey, TValue> firstSet,
        IDictionary<TKey, TValue> secondSet,
        Func<KeyValuePair<TKey, TValue>, bool> firstFilter,
        Func<KeyValuePair<TKey, TValue>, bool> secondFilter)
    {
        return firstSet
        .Where(firstFilter)
        .Concat(secondSet.Where(secondFilter))
        .GroupBy(d => d.Key)
        .ToDictionary(d => d.Key, d => d.First().Value);
    }
}

用法:

var itemsOne = new[] {
    new { Name = "A", Level = 1 },
    new { Name = "B", Level = 2 },
    new { Name = "C", Level = 3 },
    new { Name = "D", Level = 4 }
}.ToDictionary(i => i.Name, i => i);
var itemsTwo = new[] {
    new { Name = "C", Level = 10 },
    new { Name = "D", Level = 20 },
    new { Name = "E", Level = 30 },
    new { Name = "F", Level = 40 }
}.ToDictionary(i => i.Name, i => i);
itemsOne
.Combine(itemsTwo,
    kvp => kvp.Value.Level <= 3,
    kvp => kvp.Value.Level <= 30)
    .ToDictionary(d => d.Key, d=> d.Value.Level)
结果:

<>之前一个1B 2C 3D 20E 30