// O(nrlogr) instead of O(nr^2) naive algorithm (n = max length of lists, r = number of lists) public static IEnumerable <T> MergeMany <T>(this IEnumerable <IEnumerable <T> > lists, Func <T, T, T> mergeFunc) where T : IComparable <T> { var enumerators = lists.Select(list => list.GetEnumerator()).ToArray(); bool[] hasCur = new bool[enumerators.Length]; int numRunning = enumerators.Length; var BST = new SortedDictionary <ComparableWrapper <T>, KeyValuePair <Wrapper <T>, List <int> > >(); bool first = true; while (numRunning > 0) { IEnumerable <int> indices; if (first) { first = false; indices = Enumerable.Range(0, enumerators.Length); for (int i = 0; i < hasCur.Length; i++) { hasCur[i] = true; } } else { var top = BST.First(); BST.Remove(top.Key); indices = top.Value.Value; yield return(top.Key.Value); } foreach (int i in indices) { if (hasCur[i]) { if (enumerators[i].MoveNext()) { var val = enumerators[i].Current; KeyValuePair <Wrapper <T>, List <int> > res; if (BST.TryGetValue(new ComparableWrapper <T>(val), out res)) { res.Key.Value = mergeFunc(res.Key.Value, val); res.Value.Add(i); } else { var wrapper = new ComparableWrapper <T>(val); res = new KeyValuePair <Wrapper <T>, List <int> >(wrapper, new List <int>()); res.Value.Add(i); BST.Add(wrapper, res); } } else { hasCur[i] = false; numRunning--; } } } } }
public int CompareTo(ComparableWrapper <T> other) { return(_comparer.Compare(Value, other.Value)); }