3

I have a list of lists and need to eliminate all lists that have the same 3rd element, and save 1.

For example:

x=[[1,2,3],[1,3,3],[5,6,3],[2,4,6],[8,5,9],[10,5,9]]

could turn into:

x=[[1,2,3],[2,4,6],[8,5,9]]

I've attempted a solution that eliminates all lists that have the same 2nd index using lambda, but I don't know how to save one of each element like set() does--I just get:

x=[[2,4,6]]
dansalmo
11.7k5 gold badges62 silver badges55 bronze badges
asked Nov 20, 2013 at 0:10
5
  • 4
    Please post your attempt so that we can tell you where it falls short Commented Nov 20, 2013 at 0:11
  • 1
    where did [1,3,3] and [5,6,3] go? Commented Nov 20, 2013 at 0:13
  • @roippi: Presumably, since the element at index 2 in both of those lists is 3, they disappeared because [1, 2, 3] was kept. It's not clear whether the OP means index 2 counting from 0, or second element counting from 1. Commented Nov 20, 2013 at 0:14
  • @user2357112 the "second element" is the element at index 1. Commented Nov 20, 2013 at 0:15
  • I meant index 2 counting from 0, sorry. Commented Nov 20, 2013 at 0:16

6 Answers 6

8

Python sets should still work for you:

>>> seen = set()
>>> result = []
>>> for s in x:
 e = s[2]
 if e not in seen:
 result.append(s)
 seen.add(e)
>>> result
[[1, 2, 3], [2, 4, 6], [8, 5, 9]]
answered Nov 20, 2013 at 0:15

2 Comments

I kept getting set() errors like "unhashable type: list", had no idea that you can just define a variable to be an empty set like that. TY!
Bah, with Raymond in play is not even fair :)
4

You could also use a dict here, which could be a bit more flexible later:

data =[[1,2,3],[1,3,3],[5,6,3],[2,4,6],[8,5,9],[10,5,9]]
one_of = {el[2]:el for el in data}.values()
# [[10, 5, 9], [5, 6, 3], [2, 4, 6]]
answered Nov 20, 2013 at 0:22

3 Comments

Jon, we ll get only the last duplicate value but he wants only the first duplicate value.
Just reverse the data if you want the first values.
@thefourtheye well... the first occurrence is a reasonable assumption, however, it's not actually specified that's the case :) need to eliminate all lists that have the same 3rd element, and save 1
3

You can use set if you define a helper class

>>> L = [[1,2,3],[1,3,3],[5,6,3],[2,4,6],[8,5,9],[10,5,9]]
>>> class Element(list):__hash__=lambda s:hash(s[2]);__eq__=lambda s,o:s[2]==o[2]
... 
>>> set(map(Element, L))
set([[8, 5, 9], [1, 2, 3], [2, 4, 6]])
answered Nov 20, 2013 at 0:33

Comments

2

You can do this with list comprehension and helper set:

>>> t = set()
>>> y = [l for l in x if l[2] not in t and not t.add(l[2])]
>>> y
[[1, 2, 3], [2, 4, 6], [8, 5, 9]]
answered Nov 20, 2013 at 0:18

Comments

2

The itertools docs come with a nice set of recipes, one of which, unique_everseen does exactly what you want: "List unique elements, preserving order. Remember all elements ever seen."

You can copy it paste it from the recipes, or you can pip install more-itertools and just use it as more_itertools.unique_everseen.

Or you can look at the code, and see that it's essentially just a slightly more flexible and slightly optimized version of exactly what Raymond Hettinger's answer does.*

And that's exactly what the recipes are there for—when you want to do something to an iterable, there's often a recipe for it, which not only does what you want, but is so simple that if you take a couple minutes to work out how it works, you'll know how to do it yourself in the future.


* This shouldn't surprise anyone who knows anything about Python, or just looks at the source to itertools...

answered Nov 20, 2013 at 0:51

1 Comment

@RomanPekar: In that case, I should have added a link to it. (Which I've now done.)
1
>>> L = [[1,2,3],[1,3,3],[5,6,3],[2,4,6],[8,5,9],[10,5,9]]
>>> s = set(i[2] for i in L) 
>>> [s.remove(i[2]) or i for i in L if i[2] in s]
[[1, 2, 3], [2, 4, 6], [8, 5, 9]]
answered Nov 20, 2013 at 0:25

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.