请考虑以下代码:
Dictionary<int, SortedList<int, List<int>>> ddl1 = new Dictionary<int, SortedList<int, List<int>>>();
ddl1.Add(1, new SortedList<int,List<int>>());
ddl1[1].Add(2, new List<int>());
ddl1[1][2].Add(3);
ddl1[1][2].Add(4);
ddl1[1][2].Add(5);
ddl1[1].Add(3, new List<int>());
ddl1[1][3].Add(3);
ddl1[1][3].Add(4);
ddl1[1][3].Add(5);
ddl1.Add(2, new SortedList<int, List<int>>());
ddl1[2].Add(2, new List<int>());
ddl1[2][2].Add(3);
ddl1[2][2].Add(4);
ddl1[2][2].Add(5);
Dictionary<int, SortedList<int, List<int>>> ddl2 =
new Dictionary<int, SortedList<int, List<int>>>();
ddl2.Add(1, new SortedList<int, List<int>>());
ddl2[1].Add(3, new List<int>());
ddl2[1][3].Add(3);
ddl2[1][3].Add(4);
ddl2.Add(2, new SortedList<int, List<int>>());
ddl2[2].Add(2, new List<int>());
ddl2[2][2].Add(3);
我希望得到这两个复杂词典的交集。结果应包含
1 { 3 {3,4} }
2 { 2 {3 } }
有人可以帮我解决这个LINQ问题吗?此外,它是否比手动foreach和.contains方法更有效?提前谢谢!
答案 0 :(得分:2)
简而言之,最好用foreach手动完成。我想如果你真的想通过LINQ这样做,你将不得不创建一些自定义IEqualityComparer
,这不仅仅是一个手动foreach解决方案的编码工作量。
但是,如果您通过LINQ进行,则可能会受益于PLINQ。除此之外,我不明白为什么LINQ解决方案会更快。
但是,您当然可以使用Intersect
。但请记住,每当您按照评论中的建议调用ToDictionary时,您将创建一个新的字典,这是耗费时间和内存的。
因此,假设您仍然需要SortedList
,这是我能想到的最佳解决方案。如果没有,请用通常的字典替换。
var result = new Dictionary<int, SortedList<int, List<int>><();
foreach (var key1 in ddl1.Keys.Intersect(ddl2.Keys))
{
var subList1 = ddl1[key1];
var subList2 = ddl2[key1];
var common1 = new SortedList<int, List<int>>();
result.Add(key1, common1);
foreach (var key2 in subList1.Keys.Intersect(subList2.Keys))
{
var subList1L2 = subList1[key2];
var subList2L2 = subList2[key2];
var common2 = subList1L2.Intersect(subList2L2).ToList();
if (common2.Count > 0) common1.Add(key2, common2);
}
}
答案 1 :(得分:1)
诀窍是将字典键和两个词典加入SortedList键:
var q1 = from d1 in ddl1
from sl1 in d1.Value
select new { d1.Key, sl1 };
var q2 = from d2 in ddl2
from sl2 in d2.Value
select new { d2.Key, sl2 };
var q = from ds1 in q1
join ds2 in q2
on new { key1 = ds1.Key, key2 = ds1.sl1.Key }
equals new { key1 = ds2.Key, key2 = ds2.sl2.Key }
select new
{
key1 = ds1.Key,
key2 = ds1.sl1.Key,
Intersect = ds1.sl1.Value.Intersect(ds2.sl2.Value)
};
子查询(q1, q2
)将字典展平为列表列表,因此对于连接,可以组合字典键和列表键。
现在,您可以首先使用q2.AsParallel()
然后q1.AsParallel()
来衡量并行化是否确实提高了性能。
答案 2 :(得分:0)
试试这个方法:
public static IDictionary<int, SortedList<int, List<int>>> Intersect(IDictionary<int, SortedList<int, List<int>>> x, IDictionary<int, SortedList<int, List<int>>> y) {
IDictionary<int, SortedList<int, List<int>>> one = x.Keys.Intersect(y.Keys).ToDictionary(k => k, k => x[k]);
foreach (KeyValuePair<int, SortedList<int, List<int>>> kvp in one.ToList()) {
one[kvp.Key] = new SortedList<int,List<int>>(kvp.Value.Keys.Intersect(y[kvp.Key].Keys).ToDictionary(k => k, k => y[kvp.Key][k]));
}
return one;
}