Last active
December 10, 2015 23:55
-
-
Save durden/4512414 to your computer and use it in GitHub Desktop.
Snippet of timing/brainstorming multiple solutions to compare two lists without worrying about ordering
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See the following for a discussion I later found on stackoverflow, should | |
# have searched there first ;) | |
# http://stackoverflow.com/questions/1388818/how-can-i-compare-two-lists-in-python-and-return-matches | |
from timeit import timeit | |
# Different ways to implement a function that compares lists without | |
# taking into account their order | |
compare_lists_without_order = lambda x, y: sorted(x) == sorted(y) | |
compare_lists_without_order = lambda x, y: True if not len(set(x) - set(y)) else False | |
compare_lists_without_order = lambda x, y: True if set(x).intersection(y) == set(x) else False | |
def compare_lists_without_order(x, y): | |
if len(x) != len(y): | |
return False | |
for val1 in x: | |
if val1 not in y: | |
return False | |
return True | |
# Not saying any of these solutions are 'good,' just brainstorming. The set solutions | |
# have some overhead of actually creating sets, etc. This got me to thinking, which | |
# comparison method is 'faster?' | |
# Lists are not sorted | |
timeit('sorted(x) != sorted(y)', setup='x = range(10);y = range(9, -1, -1)') | |
#1.1857669353485107 | |
timeit('set(x).intersection(y)', setup='x = range(10);y = range(9, -1, -1)') | |
#1.1229619979858398 | |
timeit('set(x) - set(y)', setup='x = range(10);y = range(9, -1, -1)') | |
#1.2803409099578857 | |
timeit('compare_lists_without_order(x, y)', setup='x = range(10);y = range(9, -1, -1);from __main__ import compare_lists_without_order') | |
#1.5430231094360352 | |
# Lists are already sorted | |
timeit('set(x) - set(y)', setup='x = range(10);y = range(10)') | |
#1.2265610694885254 | |
timeit('set(x).intersection(y)', setup='x = range(10);y = range(10)') | |
#1.0897159576416016 | |
timeit('sorted(x) != sorted(y)', setup='x = range(10);y = range(10)') | |
#1.1469509601593018 | |
timeit('compare_lists_without_order(x, y)', setup='x = range(10);y = range(10);from __main__ import compare_lists_without_order') | |
#1.5693888664245605 | |
## Final thoughts | |
# -------------------------------- | |
# I think the direct solution that manually does the looping and checking the lengths | |
# might be best. It's slower, but it's a bit easier to understand and doesn't require | |
# converting to sets, etc. In addition, it will give the right answer if you deem the | |
# right answer to mean that the sets have exactly the same items just in a different | |
# (or same) order. | |
# Note that the two solutions with set will not return the correct result depending on what | |
# you want. Consider the following two lists: | |
x = range(10) | |
y = range(10) + [1] | |
# y has duplicates but using the following comparison we will not detect this | |
compare_lists_without_order = lambda x, y: True if not len(set(x) - set(y)) else False | |
compare_lists_without_order(x, y) | |
# Note that the order you do the set difference doesn't matter; remember sets don't | |
# allow duplicates so the sets created from the two lists are actually equal | |
compare_lists_without_order = lambda x, y: True if not len(set(y) - set(x)) else False | |
compare_lists_without_order(x, y) | |
# The intersection solution falls victim to the same problem: | |
compare_lists_without_order = lambda x, y: True if set(x).intersection(y) == set(x) else False | |
compare_lists_without_order(x,y) | |
# Of course the set solutions could be 'fixed' by adding a check in each of them to | |
# ensure that the lists are the same length, just as the full/direct loop solution | |
# used. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment