I'm a newbie with python and programming in general and need some help: I have a list that I've created earlier in the program by appending from a loop (i.e. I can't just redefine my list now to solve my problem), of 24 4-tuples:
elementary = [(23, 1, 18, 4), (23, 1, 6, 16), (23, 1, 4, 18), (23, 2, 18, 3), (23, 2, 12, 9), (23, 2, 9, 12), (23, 2, 3, 18), (23, 3, 18, 2), (23, 3, 2, 18), (23, 4, 18, 1), (23, 4, 1, 18), (23, 5, 14, 7), (23, 5, 7, 14), (23, 6, 16, 1), (23, 6, 9, 8), (23, 6, 8, 9), (23, 6, 1, 16), (23, 7, 14, 5), (23, 7, 5, 14), (23, 8, 9, 6), (23, 8, 6, 9), (23, 9, 12, 2), (23, 9, 8, 6), (23, 9, 6, 8), (23, 9, 2, 12), (23, 12, 9, 2), (23, 12, 2, 9), (23, 14, 7, 5), (23, 14, 5, 7), (23, 16, 1, 6), (23, 18, 4, 1), (23, 18, 3, 2), (23, 18, 2, 3), (23, 18, 1, 4)]
but now would like to get rid of the tuples that are just re-arranged... in other words, after the first tuple ((23,1,18,4)) I would let get rid of (23,1,4,18), (23,4,1,18), etc..., and if possible, I'd like to do this throughout the list, so that I only end up with 6 completely distinct 4-tuples. Is there any way to do this without going back and doing something differently earlier in my program? Any help would be greatly appreciated. Thanks!
-
2Welcome to SO. What have you tried?tacaswell– tacaswell2013年01月24日 03:35:54 +00:00Commented Jan 24, 2013 at 3:35
5 Answers 5
How about:
{tuple(sorted(t)): t for t in elementary}.values()
Comments
As a 1-liner, this sorts each 4-tuple, then creates a set of the result, shich has the effect of removing the duplicates. I'm assuming your 4-tuples are allowed to have the order of elements changed.
set(tuple(sorted(i)) for i in elementary)
>>> set((5, 7, 14, 23), (6, 8, 9, 23), (2, 3, 18, 23), (1, 4, 18, 23), (1, 6, 16, 23), (2, 9, 12, 23))
1 Comment
Do you really have only 24? If so, a slow-ish solution with some unnecessary memory allocations may work fine here, and save you programming time:
elementary_unique = set(tuple(sorted(t)) for t in elementary)
Now elementary_unique is a set rather than a list - if it matters, you can use
elementary_unique = list(set(tuple(sorted(t)) for t in elementary))
instead, but this will be a little slower than the first version.
1 Comment
You can recognize the equivalent combinations whenever sorted(tuple1) == sorted(tuple2).
The code is short and sweet:
>>> set(map(tuple, map(sorted, elementary)))
set([(5, 7, 14, 23), (6, 8, 9, 23), (2, 3, 18, 23),
(1, 4, 18, 23), (1, 6, 16, 23), (2, 9, 12, 23)])
If you need to preserve the ordering of each of the first distinct tuples, it takes a little more work:
>>> uniq = set()
>>> for t in elementary:
s = tuple(sorted(t))
if s not in uniq:
uniq.add(s)
print t
(23, 1, 18, 4)
(23, 1, 6, 16)
(23, 2, 18, 3)
(23, 2, 12, 9)
(23, 5, 14, 7)
(23, 6, 9, 8)
Comments
If you really want to get down and dirty with the comparisons:
In [1028]: elementary = [(23, 1, 18, 4), (23, 1, 6, 16), (23, 1, 4, 18), (23, 2, 18, 3), (23, 2, 12, 9), (23, 2, 9, 12), (23, 2, 3, 18), (23, 3, 18, 2), (23, 3, 2, 18), (23, 4, 18, 1), (23, 4, 1, 18), (23, 5, 14, 7), (23, 5, 7, 14), (23, 6, 16, 1), (23, 6, 9, 8), (23, 6, 8, 9), (23, 6, 1, 16), (23, 7, 14, 5), (23, 7, 5, 14), (23, 8, 9, 6), (23, 8, 6, 9), (23, 9, 12, 2), (23, 9, 8, 6), (23, 9, 6, 8), (23, 9, 2, 12), (23, 12, 9, 2), (23, 12, 2, 9), (23, 14, 7, 5), (23, 14, 5, 7), (23, 16, 1, 6), (23, 18, 4, 1), (23, 18, 3, 2), (23, 18, 2, 3), (23, 18, 1, 4)]
In [1029]: for e in elementary:
add = True
for a in answer:
if all(_e in a and e.count(_e)==a.count(_e) and len(e)==len(a) for _e in e):
add = False
if add:
answer.append(e)
In [1030]: answer
Out[1030]:
[(23, 1, 18, 4),
(23, 1, 6, 16),
(23, 2, 18, 3),
(23, 2, 12, 9),
(23, 5, 14, 7),
(23, 6, 9, 8)]