LINQ: Bepaal of twee reeksen exact dezelfde elementen bevatten

Ik moet bepalen of twee sets exact dezelfde elementen bevatten. De volgorde maakt niet uit.

Deze twee arrays moeten bijvoorbeeld als gelijk worden beschouwd:

IEnumerable<int> data = new []{3, 5, 6, 9};
IEnumerable<int> otherData = new []{6, 5, 9, 3}

De ene set kan geen elementen bevatten die niet in de andere zitten.

Kan dit worden gedaan met behulp van de ingebouwde query-operators? En wat zou de meest efficiënte manier zijn om het te implementeren, aangezien het aantal elementen kan variëren van enkele tot honderden?


Antwoord 1, autoriteit 100%

Als u de arrays als “sets” wilt behandelen en volgorde en dubbele items wilt negeren, kunt u HashSet<T>.SetEqualsmethode:

var isEqual = new HashSet<int>(first).SetEquals(second);

Anders kun je het beste beide reeksen op dezelfde manier sorteren en SequenceEqualgebruiken om ze te vergelijken.


Antwoord 2, autoriteit 39%

Ik raad aan om beide te sorteren en een element-voor-element vergelijking te maken.

data.OrderBy(x => x).SequenceEqual(otherData.OrderBy(x => x))

Ik weet niet zeker hoe snel de implementatie van OrderByis, maar als het een O(n log n)-soort is zoals je zou verwachten, is het totale algoritme O(n log n) als goed.

Voor sommige gevallen van gegevens kunt u dit verbeteren door een aangepaste implementatie van OrderBy te gebruiken die bijvoorbeeld een tellende sortering gebruikt, voor O(n+k), met k de grootte van het bereik waarin de waarden liggen.


Antwoord 3, autoriteit 4%

Als je dubbele bestanden hebt (of als je een oplossing wilt die beter presteert voor langere lijsten), zou ik zoiets als dit proberen:

static bool IsSame<T>(IEnumerable<T> set1, IEnumerable<T> set2)
{
    if (set1 == null && set2 == null)
        return true;
    if (set1 == null || set2 == null)
        return false;
    List<T> list1 = set1.ToList();
    List<T> list2 = set2.ToList();
    if (list1.Count != list2.Count)
        return false;
    list1.Sort();
    list2.Sort();
    return list1.SequenceEqual(list2);
}

UPDATE: oeps, jullie hebben gelijk — de Except()-oplossing hieronder moet beide kanten op kijken voordat je de straat oversteekt. En het heeft een slechte prestatie voor langere lijsten. Negeer onderstaande suggestie! 🙂

Hier is een eenvoudige manier om dit te doen. Merk op dat dit ervan uitgaat dat de lijsten geen duplicaten hebben.

bool same = data.Except (otherData).Count() == 0;

Antwoord 4, autoriteit 2%

Hier is een andere manier om het te doen:

IEnumerable<int> data = new[] { 3, 5, 6, 9 };
IEnumerable<int> otherData = new[] { 6, 5, 9, 3 };
data = data.OrderBy(d => d);
otherData = otherData.OrderBy(d => d);
data.Zip(otherData, (x, y) => Tuple.Create(x, y)).All(d => d.Item1 == d.Item2);

Antwoord 5

  1. Controleer eerst de lengte. Als ze anders zijn, zijn de sets anders.
  2. u kunt data.Intersect(otherData);doen en controleren of de lengte identiek is.
  3. OF, sorteer de sets eenvoudig en herhaal ze.

Antwoord 6

Controleer eerst of beide gegevensverzamelingen hetzelfde aantal elementen hebben en controleer of alle elementen in de ene verzameling in de andere voorkomen

       IEnumerable<int> data = new[] { 3, 5, 6, 9 };
        IEnumerable<int> otherData = new[] { 6, 5, 9, 3 };
        bool equals = data.Count() == otherData.Count() && data.All(x => otherData.Contains(x));

Antwoord 7

Dit zou moeten helpen:

   IEnumerable<int> data = new []{ 3,5,6,9 };
    IEnumerable<int> otherData = new[] {6, 5, 9, 3};
    if(data.All(x => otherData.Contains(x)))
    {
        //Code Goes Here
    }

Other episodes