var h1 = SortedList {
{"one", 1},
{"two", 2}
};
var h2 = SortedList {
{"two", 22},
{"three", 3}
};
如何以惯用的方式h3
以{"one", 1},{"two", 2},{"three", 3}
结束?
答案 0 :(得分:3)
您提供的示例数据有点奇怪,因为通常在键“2”之前订购键“3”。因此,我将假设常规字符串比较排序列表的键适用于此答案。
下面的方法提供了合并算法,使用在将元素添加到输出时高级的枚举器。如果列表包含具有相同键的元素,则将该值作为tie tie进行比较。
public static IEnumerable<KeyValuePair<K, V>> MergeSortedLists<K, V>(
SortedList<K, V> l1,
SortedList<K, V> l2)
where K : IComparable
where V : IComparable
{
using (var l1Iter = l1.GetEnumerator())
using (var l2Iter = l2.GetEnumerator())
{
var morel1 = l1Iter.MoveNext();
var morel2 = l2Iter.MoveNext();
while (morel1 || morel2)
{
if (!morel1)
{
yield return l2Iter.Current;
morel2 = l2Iter.MoveNext();
}
else if (!morel2)
{
yield return l1Iter.Current;
morel1 = l1Iter.MoveNext();
}
else
{
var cmp = l1.Comparer.Compare(l1Iter.Current.Key, l2Iter.Current.Key);
if (cmp < 0)
{
yield return l1Iter.Current;
morel1 = l1Iter.MoveNext();
}
else if (cmp > 0)
{
yield return l2Iter.Current;
morel2 = l2Iter.MoveNext();
}
else // keys equal: use value to break tie.
{
if (l1Iter.Current.Value.CompareTo(l1Iter.Current.Value) <= 0)
yield return l1Iter.Current;
else
yield return l2Iter.Current;
// or if l1 takes precedence, replace above 4 lines with:
// yield return l1Iter.Current;
morel1 = l1Iter.MoveNext();
morel2 = l2Iter.MoveNext();
}
}
}
}
}
用法示例:
public static void Main(params string[] args)
{
// Note: this is not an idiomatic way to instantiate sorted lists.
var h1 = new SortedList<string, int>() {
{ "one", 1 },
{ "two", 2 }
};
var h2 = new SortedList<string, int>() {
{ "three", 3 }, // because "three" < "two"
{ "two", 22 }
};
var h3 = MergeSortedLists(h1, h2);
Console.WriteLine(string.Join(", ", h3.Select(e => string.Format("{{{0}, {1}}}", e.Key, e.Value))));
// Outputs:
// {one, 1}, {three, 3}, {two, 2}
}
请注意,使用这个名为MergeWith
的扩展方法会更加惯用C#,因此可以将其称为
var h3 = h1.MergeWith(h2);
答案 1 :(得分:1)
SortedList
可以接受IDictionary
作为构造函数参数,您可以使用此解决方法来克服您的问题
class Program
{
private static void Main(string[] args)
{
var h1 = new SortedList<string, int>();
h1.Add("One", 1);
h1.Add("Two", 2);
var h2 = new SortedList<string, int>();
h2.Add("One", 1);
h2.Add("Two", 22);
h2.Add("Three", 3);
var unDict = h1.Union(h2).Distinct(new SortedListComparer()).ToDictionary(d=>d.Key,v=>v.Value);
SortedList<string,int> finSortedList = new SortedList<string,int>((IDictionary<string,int>)unDict,StringComparer.InvariantCultureIgnoreCase);
}
}
class SortedListComparer:EqualityComparer<KeyValuePair<string,int>>
{
public override bool Equals(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
{
return x.Key == y.Key;
}
public override int GetHashCode(KeyValuePair<string, int> obj)
{
return obj.Key.GetHashCode();
}
}
我知道这不是惯用语,但你可以试试;
Ater all SortedList
实施IDictionary
public class SortedList<TKey, TValue> : IDictionary<TKey, TValue>
答案 2 :(得分:1)
我冒昧地让你的问题在LinqPad4中发挥作用 基本上,和你的一样。创建两个集合(List&lt;&gt; here),然后将差异加在一起。
var h1 = new List<Tuple<string,int>>();
h1.Add(new Tuple<string,int>("one",1));
h1.Add(new Tuple<string,int>("two",2));
var h2 = new List<Tuple<string,int>>();
h2.Add(new Tuple<string,int>("two", 22));
h2.Add(new Tuple<string,int>("three",3));
var h3 = from a in h2
where !(from b in h1 select b.Item1).Contains(a.Item1)
select a;
h1.AddRange(h3);
h1.Dump();
LinqPad4链接代码。 http://share.linqpad.net/soivue.linq
答案 3 :(得分:0)
一些伪算法可以降低算法。
假设您可以遍历这些列表:
var h3 = new SortedList;
var ptrA, ptrB, ptrC = 0;
while(ptrA ! h1.length && ptrB ! h2.length){
if(h1.ptrA.key < h2.ptrB.key){
h3.ptrC.key = h1.ptrA.key;
h3.ptrC.value = h1.ptrA.key;
ptrA++;
ptrC++;
}
else if(h1.ptrA.key > h2.ptrB.key){
h3.ptrC.key = h2.ptrB.key;
h3.ptrC.value = h2.ptrB.key;
ptrB++;
ptrC++;
}
else if(h1.ptrA.key == h2.ptrB.key){
h3.ptrC.key = h1.ptrA.key;
h3.ptrC.value = h1.ptrA.key;
ptrA++;
ptrB++;
ptrC++;
}
}
也许我的同事们对这种相当强力的方法有更好的方法或者一些补充。
这里的概念很简单,因为我们为每个列表增加一些指针,我们在这个位置扼制键。根据我们发现的内容确定将哪个密钥写入列表。如果我们找到相等的对,那么我们从列表A中取值并增加所有指针,实际上留下与列表B中该键匹配的值。