Created
December 12, 2015 23:32
-
-
Save hughdbrown/c5250fab438fb28fa0d7 to your computer and use it in GitHub Desktop.
Ordered unique elements
This file contains hidden or 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
# An occasional python interview question I have seen is: | |
# "How would you make this series unique while preserving order?" | |
# The standard code looks like this: | |
def unique2(series): | |
result = [] | |
seen = set() | |
for s in series: | |
if s not in seen: | |
seen.add(s) | |
result.append(s) | |
return result | |
# And this works. Here is the extra clever python-y code you can write instead: | |
def unique(series): | |
seen = set() | |
return [seen.add(s) or s for s in series if s not in seen] | |
# The tricky part is that `set.add` returns `None` so if you `or` that with a value, | |
# you get the value plus the side effect of modifying the `set`. And if you compare the | |
# disassembled code (using the `dis` module), you can see how much shorter the clever | |
# code is: | |
``` | |
from dis import dis | |
>>> dis(unique) | |
2 0 LOAD_GLOBAL 0 (set) | |
3 CALL_FUNCTION 0 (0 positional, 0 keyword pair) | |
6 STORE_DEREF 0 (a) | |
3 9 LOAD_CLOSURE 0 (a) | |
12 BUILD_TUPLE 1 | |
15 LOAD_CONST 1 (<code object <listcomp> at 0x10deb6390, file "<stdin>", line 3>) | |
18 LOAD_CONST 2 ('unique3.<locals>.<listcomp>') | |
21 MAKE_CLOSURE 0 | |
24 LOAD_FAST 0 (series) | |
27 GET_ITER | |
28 CALL_FUNCTION 1 (1 positional, 0 keyword pair) | |
31 RETURN_VALUE | |
>>> dis(unique2) | |
2 0 BUILD_LIST 0 | |
3 STORE_FAST 1 (result) | |
3 6 LOAD_GLOBAL 0 (set) | |
9 CALL_FUNCTION 0 (0 positional, 0 keyword pair) | |
12 STORE_FAST 2 (seen) | |
4 15 SETUP_LOOP 52 (to 70) | |
18 LOAD_FAST 0 (series) | |
21 GET_ITER | |
>> 22 FOR_ITER 44 (to 69) | |
25 STORE_FAST 3 (s) | |
5 28 LOAD_FAST 3 (s) | |
31 LOAD_FAST 2 (seen) | |
34 COMPARE_OP 7 (not in) | |
37 POP_JUMP_IF_FALSE 22 | |
6 40 LOAD_FAST 2 (seen) | |
43 LOAD_ATTR 1 (add) | |
46 LOAD_FAST 3 (s) | |
49 CALL_FUNCTION 1 (1 positional, 0 keyword pair) | |
52 POP_TOP | |
7 53 LOAD_FAST 1 (result) | |
56 LOAD_ATTR 2 (append) | |
59 LOAD_FAST 3 (s) | |
62 CALL_FUNCTION 1 (1 positional, 0 keyword pair) | |
65 POP_TOP | |
66 JUMP_ABSOLUTE 22 | |
>> 69 POP_BLOCK | |
8 >> 70 LOAD_FAST 1 (result) | |
73 RETURN_VALUE | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment