c# - C#Linq结合2个字典

原文 标签 c# linq

c# linq combine 2 dictionaries

I have two Dictionary<string, Item>s. Item has a has a public property int Level.

I want to combine these two dictionaries where keys are unique and I want to be able to specify level on both.

Something like

dictionary 1 = all items that level < 10
dictionary 2 = all items level < 20

combine dictionary 2 with 1 (where Value.Level < 10)
if the Key is unique and the Value.Level < 20

I can easily do this with foreach loops. I can also do this with multiple linq queries. However i can't seem to figure out how to make this one single linq query.

Edit- Per your request John here is the code with 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));
Answer

Ok, that code makes it clear what you want to accomplish. So the end result should be a dictionary comprised of the items from both dictionaries that meet the specified level. If an item exists in both dictionaries than the item from the first dictionary will be preferred. While it is possible to accomplish this in a single Linq query you would end up repeating some work. Here is what I came up with, it runs in LinqPad if you want to try it out easily.

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, Item>Item具有一个公共属性int Level

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

就像是

dictionary 1 = all items that level < 10
dictionary 2 = all items level < 20

combine dictionary 2 with 1 (where Value.Level < 10)
if the Key is unique and the Value.Level < 20

I can easily do this with foreach loops. I can also do this with multiple linq queries. However i can't seem to figure out how to make this one single linq query.

Edit- Per your request John here is the code with 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));
最佳答案
好的,该代码可以清楚地说明您要完成什么。因此,最终结果应为字典,其中包含满足指定级别的两个字典中的项目。如果两个词典中都存在一个项目,则首选第一个词典中的项目。尽管可以在单个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);
相关推荐

c# - Silverlight-从部分中删除隐式样式

c# - 如何将BoundField转换为HyperLinkField?

c# - 如何获得父级AppDomain?

c# - 枚举值的生成常数

c# - 关于python正则表达式的两个问题

c# - 连接来自C#中两个数据库的表

c# - C#委托具有不同可选参数的方法

c# - 使用货币时的最佳做法

c# - LINQ to XML C#获取根元素属性

c# - C#网络凭据未传递到服务器?