Clause de non-responsabilité Ceci est une optimisation prématurée. Pour vos tableaux d'exemple, utilisez les méthodes d'extension 3.5. Jusqu'à ce que vous sachiez que vous avez un problème de performance dans cette région, vous devez utiliser le code de la bibliothèque.
Si vous pouvez trier les tableaux, ou ils sont triés quand vous arrivez à ce point dans le code, vous pouvez utiliser les méthodes suivantes.
Ils vont tirer un élément des deux, et produire l'élément "le plus bas", puis aller chercher un nouvel élément de la source correspondante, jusqu'à épuisement des deux sources. Dans le cas où l'élément actuel extrait des deux sources est égal, il produira celui de la première source, et les ignorera dans les deux sources.
private static IEnumerable<T> Merge<T>(IEnumerable<T> source1,
IEnumerable<T> source2)
{
return Merge(source1, source2, Comparer<T>.Default);
}
private static IEnumerable<T> Merge<T>(IEnumerable<T> source1,
IEnumerable<T> source2, IComparer<T> comparer)
{
#region Parameter Validation
if (Object.ReferenceEquals(null, source1))
throw new ArgumentNullException("source1");
if (Object.ReferenceEquals(null, source2))
throw new ArgumentNullException("source2");
if (Object.ReferenceEquals(null, comparer))
throw new ArgumentNullException("comparer");
#endregion
using (IEnumerator<T>
enumerator1 = source1.GetEnumerator(),
enumerator2 = source2.GetEnumerator())
{
Boolean more1 = enumerator1.MoveNext();
Boolean more2 = enumerator2.MoveNext();
while (more1 && more2)
{
Int32 comparisonResult = comparer.Compare(
enumerator1.Current,
enumerator2.Current);
if (comparisonResult < 0)
{
// enumerator 1 has the "lowest" item
yield return enumerator1.Current;
more1 = enumerator1.MoveNext();
}
else if (comparisonResult > 0)
{
// enumerator 2 has the "lowest" item
yield return enumerator2.Current;
more2 = enumerator2.MoveNext();
}
else
{
// they're considered equivalent, only yield it once
yield return enumerator1.Current;
more1 = enumerator1.MoveNext();
more2 = enumerator2.MoveNext();
}
}
// Yield rest of values from non-exhausted source
while (more1)
{
yield return enumerator1.Current;
more1 = enumerator1.MoveNext();
}
while (more2)
{
yield return enumerator2.Current;
more2 = enumerator2.MoveNext();
}
}
}
Notez que si l'une des sources contient des doublons, vous pouvez voir des doublons dans la sortie. Si vous souhaitez supprimer ces doublons dans les listes déjà triés, utilisez la méthode suivante:
private static IEnumerable<T> CheapDistinct<T>(IEnumerable<T> source)
{
return CheapDistinct<T>(source, Comparer<T>.Default);
}
private static IEnumerable<T> CheapDistinct<T>(IEnumerable<T> source,
IComparer<T> comparer)
{
#region Parameter Validation
if (Object.ReferenceEquals(null, source))
throw new ArgumentNullException("source");
if (Object.ReferenceEquals(null, comparer))
throw new ArgumentNullException("comparer");
#endregion
using (IEnumerator<T> enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
T item = enumerator.Current;
// scan until different item found, then produce
// the previous distinct item
while (enumerator.MoveNext())
{
if (comparer.Compare(item, enumerator.Current) != 0)
{
yield return item;
item = enumerator.Current;
}
}
// produce last item that is left over from above loop
yield return item;
}
}
}
Notez qu'aucun de ces utilisera en interne une structure de données pour conserver une copie des données, donc ils seront pas cher si l'entrée est triée. Si vous ne pouvez pas, ou ne le garantirez pas, vous devriez utiliser les méthodes d'extension 3.5 que vous avez déjà trouvées.
exemple de code est ici qui appelle les méthodes ci-dessus:
String[] list_1 = { "apple", "orange", "apple", "banana" };
String[] list_2 = { "banana", "pear", "grape" };
Array.Sort(list_1);
Array.Sort(list_2);
IEnumerable<String> items = Merge(
CheapDistinct(list_1),
CheapDistinct(list_2));
foreach (String item in items)
Console.Out.WriteLine(item);
Je suis revenu à ce sujet pour poster exactement cette solution. C'est idéal dans tous les sens, je crois! –
Un point mineur, mais le type de retour de Union est IEnumerable, donc vous devrez ajouter un ToArray() pour obtenir la chaîne [] –
Ceci est toujours utile 10 ans après: D – Jen