6

I have a list with nested lists, which contain tuples. The list looks like this:

428 [(' whether', None), (' mated', None), (' rooster', None), ('', None)]
429 [(' produced', None), (' without', None), (' rooster', None), (' infertile', None), ('', None)]

I would like to be able access the "None" elements of the tuple, per index value. I would like to create a new list with the same index values that would look like:

428 [(None, None, None, None)]
429 [(None, None, None, None, None)]

I don't really care what type the "None" is in. I just want them as a separate list.

I've tried list comprehensions, but I only can retrieve the tuples themselves, not the elements inside.

Any help would be appreciated.

wRAR
  • 25,009
  • 4
  • 84
  • 97
user1882766
  • 201
  • 1
  • 3
  • 10
  • Can you show the actual list (as a Python list display that we can type into the interpreter)? Is it `[428, [(...)], 429, [(...)], ...]`? Or something different? – abarnert Feb 13 '13 at 22:21
  • 3
    In your example the "None" is always the second value in the tuple. If that's the case you could do [ x[1] for x in myList ] – Roy Nieterau Feb 13 '13 at 22:21
  • 2
    Also, what is the list comprehension you tried that can only retrieve the `tuple`s? Is there a reason you can't just stick `[1]` on the end of the expression? – abarnert Feb 13 '13 at 22:21
  • `[y for x,y in a_list]`??? I probably missread the question. – Niclas Nilsson Feb 13 '13 at 22:22

6 Answers6

11

Simplest for just a single list containing tuples would be:

[x[1] for x in myList]
# [None, None, None, None]

Or if it's always the last value in the tuple (if it contains more than two values):

[x[-1] for x in myList]
# [None, None, None, None]

Note that these examples below are using nested lists. It's a list of lists that contain tuples. I figured that's what you were looking for since you were showing two variations of the lists.

Use a nested comprehension list:

myList =[ [(' whether', None), (' mated', None), (' rooster', None), ('', None)] ,
          [(' produced', None), (' without', None), (' rooster', None), (' infertile', None), ('', None)] ]


print [[x[1] for x in el] for el in myList]
# [[None, None, None, None], [None, None, None, None, None]]

Or some other variations:

myList =[ [(None, None), (' mated', None), (' rooster', None), ('', None)] ,
              [(' produced', None), (' without', None), (' rooster', None), (' infertile', None), ('', None)] ]

# If there are multiple none values (if the tuple isn't always just two values)
print [ [ [ x for x in z if x == None] for z in el ] for el in myList ]
# [[[None, None], [None], [None], [None]], [[None], [None], [None], [None], [None]]]

# If it's always the last value in the tuple
print [[x[-1] for x in el] for el in myList]
# [[None, None, None, None], [None, None, None, None, None]]

Also see: SO: Understanding nested list comprehension

Community
  • 1
  • 1
Roy Nieterau
  • 1,226
  • 2
  • 15
  • 26
7

You can address the elements inside a tuple in the same way as you would with the elements of a list: using indexes. For example:

lst = [1, (2, 3)]
lst[1][1] # first index accesses tuple, second index element inside tuple
=> 3
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • I've actually tried the list comprehension that Roy suggested. What that does is put all the tuples in one big list. If it use the method discussed by Oscar, I retrieve only the first tuple in the list. – user1882766 Feb 13 '13 at 22:32
  • @user1882766: You have to give us your actual list, and the actual list comprehension you tried. If you only give us vague descriptions, we're all just guessing at how your structured the comprehension and where to put all the indices and so on, and we're likely to guess wrong. – abarnert Feb 13 '13 at 22:37
  • 1
    @user1882766 I'm just showing how to access the elements in a tuple inside a list, for processing the entire list 1) you have to provide a correctly formed list (that's not the case in the code of the question) and 2) you have to iterate over each element, be it with a list comprehension or any other looping mechanism – Óscar López Feb 13 '13 at 22:38
0

If you just want to get None if it exists in the tuple:

tuple([None for t in list if None in t])

This would recreate a tuple containing None for each tuple it is in. Note that this would not be a good solution if you wanted the # of None's in total.

TheDude
  • 3,796
  • 2
  • 28
  • 51
0

The thing you showed isn't actually a list, and it's hard to guess what the actual list might be. But I'm going to assume it's something like this:

list_o_lists = [428,
 [(' whether', None), (' mated', None), (' rooster', None), ('', None)],
 429,
 [(' produced', None),
  (' without', None),
  (' rooster', None),
  (' infertile', None),
  ('', None)]]

Any list comprehension to access the tuples within that is already going to be pretty horrible:

[[tup for tup in lst] if is_sequence(lst) else lst for lst in list_o_lists]

But modifying it to access the second element of each tuple is trivial:

[[tup[1] for tup in lst] if is_sequence(lst) else lst for lst in list_o_lists]

Really, no matter what your list comprehension is, no matter how horrible it is, based on your question, somewhere you've got each tuple as an expression, which means all you have to do is put a [1] on that expression.


From your comment:

Sorry, the numbers are the index values.

I think you actually have something simpler:

list_o_lists = [
 [(' whether', None), (' mated', None), (' rooster', None), ('', None)],
 [(' produced', None),
  (' without', None),
  (' rooster', None),
  (' infertile', None),
  ('', None)]]

And then your attempted list comprehension was probably something like this:

[[tup for tup in lst] for lst in list_o_lists]

Of course this is just a guess, because you still haven't shown us your actual list, or the list comprehension you tried. But as I said above: "… no matter what your list comprehension is… somewhere you've got each tuple as an expression, which means all you have to do is put a [1] on that expression."

So, this one is just as easy to change as the one above:

[[tup[1] for tup in lst] for lst in list_o_lists]

And if it's not what you actually have, then what you actually have will also be just as easy to change. But you'll have to do it yourself, because we have all failed in our repeated attempts to read your mind, while you have your actual code in front of you.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Sorry, the numbers are the index values. I included them because I would like to keep the "Nones" at the same index. – user1882766 Feb 13 '13 at 22:52
0

use zip with the * to expand the list into args:

x = [(' whether', None), (' mated', None), (' rooster', None), ('', None)]
stuff, nones = zip(*x)
# prints: stuff
#(' whether', ' mated', ' rooster', '')
print nones
# prints: (None, None, None, None)

zip works by taking a bunch of lists and making the first element of every argument into a list, and the second argument into a list ect

the asterisks (*) expands the list so you can imagine zip(*x) as zip(x[0],x[1], x[2],...x[n])

jcr
  • 1,015
  • 6
  • 18
0

I suppose that 428 and 429 are indexes not present in the list.

So, given the question

li = [[(' whether', None), (' mated', None),
       (' rooster', None), ('', None)],

      [(' produced', None), (' without', None),
       (' rooster', None), (' infertile', None),
       ('', None)]

      ]


print [ [len(subli)*(None,)] for subli in li]

will do the job.

[[(None, None, None, None)], [(None, None, None, None, None)]]

Your question is strange. What will be the use of such data ?

eyquem
  • 26,771
  • 7
  • 38
  • 46