8
votes

Complémentation de deux listes?

permet de dire que j'ai une liste de chaînes:

a, b, c, d

une autre liste de chaînes

b, c, d

Je veux savoir quels éléments sont dans la première liste qui ne figurent pas dans la deuxième liste. Le résultat serait donc un

Je ne connais pas le nom de la méthode d'extension pour le faire est. Je sais que je peux utiliser Concat, Union, intersect pour des comparaisons de liste similaires, mais je ne connais tout simplement pas le nom pour accomplir cette tâche particulière.

addendum, je suis intéressé par des duplicats, donc si la première liste est:

a, a, a, b, c, d

et la deuxième liste est

b, c, d

Je veux obtenir

a, a, a

Merci!


2 commentaires

Utilisez des ensembles si vous faites cela avec plus de quelques reprises avec de petites listes. Ce n'est pas seulement l'approche la plus appropriée, également mille fois mieux complexité-sage.


Merci, le problème implique des milliers de lignes


4 Réponses :


4
votes
var result = list1.Where(i => !list2.Contains(i));

6 commentaires

Il n'y a pas une méthode d'extension intégrée pour cela?


Vous pouvez créer une méthode d'extension qui le fait.


Je vois que cela est nettement plus lent que l'intégré sauf, mais puisqu'il contient des doublons, je vais l'utiliser (pour l'instant) merci! :)


Êtes-vous en train de dire que le temps de traitement est plus lent?


Oui, il faut beaucoup plus de temps à traiter. Le fait qu'il y ait deux méthodes syndicales pour les doublons et aucun doublé me ​​jette. Ne devrait-il pas y avoir deux méthodes de doublons et aucun doublons pour sauf aussi bien?


@Rock: Ceci est O (n ^ 2) , alors que sauf est o (n) .




4
votes

La méthode "sauf" dans le BCL supprime tous les doublons, ce qui n'est pas ce que vous voulez.

Si les listes du problème sont grandes, alors de le faire efficacement, vous voulez probablement perdre la mémoire en échange de l'économie de temps. Quelque chose comme: p> xxx pré>

de cette façon, vous obtenez une recherche rapide chaque fois que vous testez un élément. P>

Appliquez-le avec P>

var sequence = new List<string>() { A, B, A, C, D };
var except = new List<string>() { B, C };
var result = sequence.Filter(except).ToList();


1 commentaires

Notez que si la première liste est A, A, B et la deuxième liste A, cela reviendra B.



0
votes

Si votre définition des doublons inclut les deux listes et strud>, vous souhaitez calculer efficacement le complément, vous devrez utiliser une structure de données différente: un sac. Un sac est un ensemble qui permet des duplicats.

Voici une méthode d'extension appelée BagDiffefence Code> Cela représente efficacement des doublons dans l'une des listes avec un exemple de programme inspiré par ERIC'S Reshante. P>

public class Bag<T> : Dictionary<T, int>
{
    public Bag(IEnumerable<T> sequence)
    {
        foreach (var item in sequence)
        {
            if (!ContainsKey(item)) this[item] = 0;
            ++this[item];
        }
    }
}

public static class EnumerableExtensions
{
    public static IEnumerable<T> BagDifference<T>(this IEnumerable<T> sequence1, IEnumerable<T> sequence2)
    {
        var bag1 = new Bag<T>(sequence1);
        var bag2 = new Bag<T>(sequence2);
        foreach (var item in bag1.Keys)
        {
            var count1 = bag1[item];
            var count2 = bag2.ContainsKey(item) ? bag2[item] : 0;
            var difference = Math.Max(0, count1 - count2);
            for (int i = 0; i < difference; i++)
                yield return item;
        }
    }
}

class Program
{

    static void Main(string[] args)
    {
        var sequence = new List<string>() { "A", "B", "A", "C", "D" };
        var except = new List<string>() { "A", "B", "C", "C" };
        var difference = sequence.BagDifference(except).ToList();
    }
}


0 commentaires