我有两个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
我可以使用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));
答案 0 :(得分:3)
如果您可以在foreach循环中轻松完成所需的操作,那么您已经编写了代码。这告诉我foreach代码可能比复杂的LINQ查询更易读,更容易维护。
这听起来像是将foreach循环代码保留到位的完美案例。 LINQ可能更新,但并不总是意味着它更好。
答案 1 :(得分:2)
好的,该代码清楚地说明了您想要完成的任务。因此,最终结果应该是由两个词典中满足指定级别的项目组成的字典。如果两个词典中都存在一个项目,那么首选词典中的项目将是首选项目。虽然可以在单个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);
答案 2 :(得分:0)
如果我不知道你纠正了:你想要在两个字典中都有记录。无论如何,我的例子可以根据您的特定需求量身定制。
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 [“key”]。Value1和merged [“key”]。Value2 例如,我使用了匿名类型(new {})。因此,您只能在同一方法或绑定中访问Value1和Value2,因为它们无论如何都是动态的。 在其他情况下,您应该创建一个类型来存储组合结果。
答案 3 :(得分:0)
以下是我认为适用于此方案的扩展程序。
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)
结果:
A 1 B 2 C 3 D 20 E 30