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));
如果您可以轻松地在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