J'ai plusieurs énormes triés énumérable séquences que je veux fusionner. Ces listes sont manipulées en tant que IEnumerable
mais sont déjà triés. Depuis l'entrée listes sont triées, il devrait être possible de les fusionner en un seul voyage, sans re-trier quoi que ce soit.
Je tiens à garder les différés de comportement à l'exécution.
J'ai essayé d'écrire un algorithme naïf qui le faire (voir ci-dessous). Cependant, il semble assez moche et je suis sûr qu'il peut être optimisé. Il peut exister un plus académique de l'algorithme...
IEnumerable<T> MergeOrderedLists<T, TOrder>(IEnumerable<IEnumerable<T>> orderedlists,
Func<T, TOrder> orderBy)
{
var enumerators = orderedlists.ToDictionary(l => l.GetEnumerator(), l => default(T));
IEnumerator<T> tag = null;
var firstRun = true;
while (true)
{
var toRemove = new List<IEnumerator<T>>();
var toAdd = new List<KeyValuePair<IEnumerator<T>, T>>();
foreach (var pair in enumerators.Where(pair => firstRun || tag == pair.Key))
{
if (pair.Key.MoveNext())
toAdd.Add(pair);
else
toRemove.Add(pair.Key);
}
foreach (var enumerator in toRemove)
enumerators.Remove(enumerator);
foreach (var pair in toAdd)
enumerators[pair.Key] = pair.Key.Current;
if (enumerators.Count == 0)
yield break;
var min = enumerators.OrderBy(t => orderBy(t.Value)).FirstOrDefault();
tag = min.Key;
yield return min.Value;
firstRun = false;
}
}
La méthode peut être utilisée comme ça:
// Person lists are already sorted by age
MergeOrderedLists(orderedList, p => p.Age);
en supposant que les suivantes, Person
classe existe quelque part:
public class Person
{
public int Age { get; set; }
}
Les doublons doivent être conservées, nous ne se soucient pas de leur ordre dans la nouvelle séquence. Voyez-vous une optimisation évidente que je pourrais utiliser?