[英]zipping/merging two sorted lists
我有两个都带有类型签名的分类字典
即
SortedDictionary<decimal, long> A
SortedDictionary<decimal, long> B
我想合并键相同的两个列表,从而创建一个新列表,例如
SortedDictionary<decimal, KeyValuePair<long,long>>
or
SortedDictionary<decimal, List<long>>
这可能不是解决情况的最佳方法,但是有人可以告诉我如何执行此方法或更好的解决方法。
这就是我得到的:
SortedDictionary<decimal, List<long>> merged = new SortedDictionary<decimal, List<long>>
(
A.Union(B)
.ToLookup(x => x.Key, x => x.Value)
.ToDictionary(x => x.Key, x => new List<long>(x))
);
编辑:上面的解决方案选择两个集合中不包含的键。 这应该选择键相同的地方:
SortedDictionary<decimal, List<long>> merged = new SortedDictionary<decimal, List<long>>
(
A.Where(x=>B.ContainsKey(x.Key))
.ToDictionary(x => x.Key, x => new List<long>(){x.Value, B[x.Key]})
);
我认为这样做的另一种LINQ方式可以更好地捕捉设置操作的意图:
SortedDictionary<decimal, long> a = new SortedDictionary<decimal, long>();
SortedDictionary<decimal, long> b = new SortedDictionary<decimal, long>();
a.Add(0, 10);
a.Add(1, 10);
a.Add(2, 100);
a.Add(100, 1);
b.Add(0, 4);
b.Add(4, 4);
b.Add(2, 10);
var result = a.Union(b)
.GroupBy(x => x.Key)
.ToDictionary(x => x.Key, x => x.Select(y => (long)y.Value).ToList());
尝试这样的事情,这并不容易:
Dictionary<decimal, long> dic1 = new Dictionary<decimal, long>{ {3,23}, {2,3}, {5,4}, {6,8}};
Dictionary<decimal, long> dic2 = new Dictionary<decimal, long>{ {3,2}, {2,5}, {5,14}, {12,2}};
//recover shared keys (the keys that are present in both dictionaries)
var sharedKeys = dic1.Select(dic => dic.Key).Intersect(dic2.Select(d2=>d2.Key));
sharedKeys.Dump();
//add to the fìnal dictionary
var final = new Dictionary<decimal, List<long>>();
foreach(var shk in sharedKeys) {
if(!final.ContainsKey(shk))
final[shk] = new List<long>();
final[shk].Add(dic1[shk]);
final[shk].Add(dic2[shk]);
}
**EDIT**
//Skip below part if you need only keys present on both dictionaries.
///-----------------------------------------------------------------
//get unique keys present in Dic1 and add
var nonsharedkeys1 = dic1.Select(d=>d.Key).Where(k=>!sharedKeys.Contains(k));
foreach(var nshk in nonsharedkeys1) {
final[nshk] = new List<long>();
final[nshk].Add(dic1[nshk]);
}
//get unique keys present in Dic2 and add
var nonsharedkeys2 = dic2.Select(d=>d.Key).Where(k=>!sharedKeys.Contains(k));
foreach(var nshk in nonsharedkeys2) {
final[nshk] = new List<long>();
final[nshk].Add(dic2[nshk]);
}
应该为您工作。
您可以简单地使用LINQ来做到这一点:
var query = from a in A
join b in B
on a.Key equals b.Key
select new {
Key = a.Key,
Value = Tuple.Create(a.Value, b.Value)
};
var merged = new SortedDictionary<decimal, Tuple<long, long>>(
query.ToDictionary(x => x.Key, x => x.Value)
);
我认为您应该在合并字典中使用Tuple<long, long>
作为您的TValue
。
您可以像这样“滥用” Concat
和Aggregate
:
var A = new SortedDictionary<decimal,long>();
var B = new SortedDictionary<decimal,long>();
A.Add(1, 11);
A.Add(2, 22);
A.Add(3, 33);
B.Add(2, 222);
B.Add(3, 333);
B.Add(4, 444);
var C = A.Concat(B).Aggregate(
new SortedDictionary<decimal, List<long>>(),
(result, pair) => {
List<long> val;
if (result.TryGetValue(pair.Key, out val))
val.Add(pair.Value);
else
result.Add(pair.Key, new[] { pair.Value }.ToList());
return result;
}
);
foreach (var x in C)
Console.WriteLine(
string.Format(
"{0}:\t{1}",
x.Key,
string.Join(", ", x.Value)
)
);
结果输出:
1: 11
2: 22, 222
3: 33, 333
4: 444
这与您编写“普通” foreach
几乎相同,并且实际上可以在任何IEnumerable<KeyValuePair<decimal, long>>
(不仅是SortedDictionary<decimal, long>
)上工作,并且很容易扩展到两个以上输入集合(如果需要)。
不幸的是,它也完全忽略了输入SortedDictionary
被很好地排序的事实,因此性能不是最佳的。 为了获得最佳性能,您必须为每个输入排序的字典线性推进独立的IEnumerator
,同时不断比较基础元素-您可以完全避免TryGetValue
这样...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.