web-dev-qa-db-fra.com

Comment affirmer que deux listes contiennent les mêmes éléments en Python?

Lors de la rédaction de scénarios de test, il est souvent nécessaire d'affirmer que deux listes contiennent les mêmes éléments sans tenir compte de leur ordre.

Je l'ai fait en convertissant les listes en ensembles.

Y a-t-il un moyen plus simple de faire cela?

EDIT:

Comme @MarkDickinson l'a souligné, je peux simplement utiliser TestCase.assertItemsEqual .

Note que TestCase.assertItemsEqual est nouveau dans Python2.7. Si vous utilisez une version antérieure de Python, vous pouvez utiliser nittest2 - un backport contenant les nouvelles fonctionnalités de Python 2.7.

130
satoru

Version légèrement plus rapide de la mise en oeuvre (Si vous savez que la plupart des listes de couples auront des longueurs différentes):

def checkEqual(L1, L2):
    return len(L1) == len(L2) and sorted(L1) == sorted(L2)

Comparant:

>>> timeit(lambda: sorting([1,2,3], [3,2,1]))
2.42745304107666
>>> timeit(lambda: lensorting([1,2,3], [3,2,1]))
2.5644469261169434 # speed down not much (for large lists the difference tends to 0)

>>> timeit(lambda: sorting([1,2,3], [3,2,1,0]))
2.4570400714874268
>>> timeit(lambda: lensorting([1,2,3], [3,2,1,0]))
0.9596951007843018 # speed up
47
defuz

À partir de Python 3.2 unittest.TestCase.assertItemsEqual ( doc ) a été remplacé par unittest.TestCase.assertCountEqual ( doc ) qui fait exactement ce que vous êtes recherchez, comme vous pouvez le lire dans le python documentation de la bibliothèque standard . La méthode est nommée de manière trompeuse mais elle fait exactement ce que vous recherchez.

a et b ont les mêmes éléments dans le même nombre, quel que soit leur ordre

Voici un exemple simple qui compare deux listes ayant les mêmes éléments mais dans un ordre différent.

  • en utilisant assertCountEqual le test réussira
  • en utilisant assertListEqual le test échouera à cause de la différence d'ordre des deux listes

Voici un petit exemple de script.

import unittest


class TestListElements(unittest.TestCase):
    def setUp(self):
        self.expected = ['foo', 'bar', 'baz']
        self.result = ['baz', 'foo', 'bar']

    def test_count_eq(self):
        """Will succeed"""
        self.assertCountEqual(self.result, self.expected)

    def test_list_eq(self):
        """Will fail"""
        self.assertListEqual(self.result, self.expected)

if __== "__main__":
    unittest.main()

Note latérale: Assurez-vous que les éléments des listes que vous comparez sont triables.

108
flazzarini

Donné

l1 = [a,b]
l2 = [b,a]

Dans Python > = 3.0

assertCountEqual(l1, l2) # True

Dans Python > = 2.7 , la fonction ci-dessus a été nommée:

assertItemsEqual(l1, l2) # True

Dans Python <2.7

import unittest2
assertItemsEqual(l1, l2) # True

via le module six (toute version Python)

import unittest
import six
class MyTest(unittest.TestCase):
    def test(self):
        six.assertCountEqual(self, self.l1, self.l2) # True
25
Cory Klein

La conversion de vos listes en ensembles vous indiquera qu’elles contiennent les mêmes éléments. Mais cette méthode ne peut pas confirmer qu'ils contiennent le même nombre d'éléments. Par exemple, votre méthode échouera dans ce cas:

L1 = [1,2,2,3]
L2 = [1,2,3,3]

Il est probablement préférable de trier les deux listes et de les comparer:

def checkEqual(L1, L2):
    if sorted(L1) == sorted(L2):
        print "the two lists are the same"
        return True
    else:
        print "the two lists are not the same"
        return False

Notez que cela ne modifie pas la structure/le contenu des deux listes. Au contraire, le tri crée deux nouvelles listes

19
inspectorG4dget

Besoin assurer la bibliothèque mais vous pouvez comparer la liste en:

assure ([1, 2]). contient_seulement ([2, 1])

Cela ne déclenchera pas d'exception d'assertion. La documentation de thin est vraiment mince, je vous conseille donc de regarder assurez-vous que les codes sont sur github

1
radeklos