Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For loop for second items in list of lists only. (python)

What I have

is something like this

def mymethod():
    return [[1,2,3,4],
            [1,2,3,4],
            [1,2,3,4],
            [1,2,3,4]]

mylist = mymethod()

for _, thing, _, _ in mylist:
    print thing

# this bit is meant to be outside the for loop, 
# I mean it to represent the last value thing was in the for
if thing:
    print thing

What I want

what I want to do is avoid the dummy variables, is there a smarter way to do this than

for thing in mylist:
    print thing[1]

because then i would have to use thing[1] any other time I needed it, without assigning it to a new variable and then things are just getting messy.

newish to python so sorry if I'm missing something obvious

like image 697
Jacxel Avatar asked Apr 13 '12 11:04

Jacxel


People also ask

Can you loop through 2 lists in Python?

Use the zip() Function to Iterate Over Two Lists in Python Python zip function enables us to iterate over two or more lists by running until the smaller list gets exhausted.

How do I iterate every other item in a list?

To get every other element in a Python list you can use the slice operator and use the fact that this operator allows to provide a step argument (with its extended syntax). Another approach is to use the mathematical concept of remainder and apply it to list indexes.

Can you use a for loop in a list Python?

In Python, we can loop over list elements with for and while statements, and list comprehensions.

How do you append to a list in a for loop in Python?

Use the append() method to add elements to a list while iterating over the list. Means you can add item in the list using loop and append method.


5 Answers

You could hack a generator expression

def mymethod():
    return [[1,2,3,4],
            [1,2,3,4],
            [1,2,3,4],
            [1,2,3,4]]

mylist = mymethod()

for thing in (i[1] for i in mylist):
    print thing

# this bit is meant to be outside the for loop, 
# I mean it to represent the last value thing was in the for
if thing:
    print thing
like image 94
Kien Truong Avatar answered Oct 17 '22 00:10

Kien Truong


If you want to get the second column of an array, you could use a list comprehension, like so:

a = [ [ 1, 2, 3, 4 ],
      [ 5, 6, 7, 8 ],
      [ 9,10,11,12 ],
      [13,14,15,16 ] ]


second_column = [ row[1] for row in a ]
# you get [2, 6, 10, 14]

You can wrap this up in a function:

def get_column ( array, column_number ):
    try:
        return [row[column_number] for row in array]
    except IndexError:
        print ("Not enough columns!")
        raise # Raise the exception again as we haven't dealt with the issue.

fourth_column = get_column(a,3)
# you get [4, 8, 12, 16]

tenth_column = get_column(a,9)
# You requested the tenth column of a 4-column array, so you get the "not enough columns!" message.

Though really, if you're working with rectangular arrays of numbers, you want to be using numpy arrays, not lists of lists of numbers.


Or, by Lattyware's implied request, a generator version:

def column_iterator ( array, column_number ):
    try:
        for row in array:
            yield row[column_number]
    except IndexError:
        print ("Not enough columns!")
        raise

Usage is just like a normal list:

>>> for item in column_iterator(a,1):
...    print(item)
... 
2
6
10
14
>>> 

The generator-nature is evident by:

>>> b = column_iterator(a,1)
>>> b.next()
2
>>> b.next()
6
>>> b.next()
10
>>> b.next()
14
like image 25
Li-aung Yip Avatar answered Oct 17 '22 00:10

Li-aung Yip


Definitely, when would itertools.chain and slicing come into help?

for thing in itertools.islice(itertools.chain(*mylist),1,None,len(mylist)):
    print(thing)

Numpy is also helpful for column slicing. Here is another example in numpy

for thing in numpy.array(mylist)[:,1]:
    print(thing)
like image 20
Abhijit Avatar answered Oct 17 '22 00:10

Abhijit


While I like Dikei's answer for clarity and terseness, I still believe that a good option is simply:

for sublist in mylist:
    item = sublist[1]
    ...
    do_stuff(item)
    ...
    do_other_stuff(item)
    ...

It remains clear, can be expanded to do more easily, and is probably the fastest.

Here are some quick tests - I'm not sure about how accurate they will be thanks to doing nothing in the loop, but they probably give an idea:

python -m timeit -s "mylist = [range(1,8) for _ in range(1,8)]" 'for thing in mylist:' '    item=thing[1]' '    pass'
1000000 loops, best of 3: 1.25 usec per loop

python -m timeit -s "mylist = [range(1,8) for _ in range(1,8)]" 'for thing in (i[1] for i in mylist):' '    pass'
100000 loops, best of 3: 2.37 usec per loop

python -m timeit -s "mylist = [range(1,8) for _ in range(1,8)]" 'for thing in itertools.islice(itertools.chain(*mylist),1,None,len(mylist)):' '    pass'
1000000 loops, best of 3: 2.21 usec per loop

python -m timeit -s "import numpy" -s "mylist = numpy.array([range(1,8) for _ in range(1,8)])" 'for thing in mylist[:,1]:' '    pass' 
1000000 loops, best of 3: 1.7 usec per loop

python -m timeit -s "import numpy" -s "mylist = [range(1,8) for _ in range(1,8)]" 'for thing in numpy.array(mylist)[:,1]:' '    pass'
10000 loops, best of 3: 63.8 usec per loop

Note that numpy is fast if once generated, but very slow to generate on demand for a single operation.

On large lists:

python -m timeit -s "mylist = [range(1,100) for _ in range(1,100)]" 'for thing in mylist:' '    item=thing[1]' '    pass'
100000 loops, best of 3: 16.3 usec per loop

python -m timeit -s "mylist = [range(1,100) for _ in range(1,100)]" 'for thing in (i[1] for i in mylist):' '    pass'
10000 loops, best of 3: 27 usec per loop

python -m timeit -s "mylist = [range(1,100) for _ in range(1,100)]" 'for thing in itertools.islice(itertools.chain(*mylist),1,None,len(mylist)):' '    pass'
10000 loops, best of 3: 101 usec per loop

python -m timeit -s "import numpy" -s "mylist = numpy.array([range(1,100) for _ in range(1,100)])" 'for thing in mylist[:,1]:' '    pass'
100000 loops, best of 3: 8.47 usec per loop

python -m timeit -s "import numpy" -s "mylist = [range(1,100) for _ in range(1,100)]" 'for thing in numpy.array(mylist)[:,1]:' '    pass'
100 loops, best of 3: 3.82 msec per loop

Remember that speed should always come second to readability, unless you really need it.

like image 26
Gareth Latty Avatar answered Oct 16 '22 23:10

Gareth Latty


The method itemgetter() can be used to solve this:

from operator import itemgetter

def mymethod():
    return [[1,2,3,4],
            [1,2,3,4],
            [1,2,3,4],
            [1,2,3,4]]

mylist = mymethod()

row = map(itemgetter(2), mylist)
print("row %s" % row)

thing = row[-1]

# this bit is meant to be outside the for loop, 
# I mean it to represent the last value thing was in the for
if thing:
    print thing

The output is:

row [3, 3, 3, 3]
3
like image 23
Andreas Florath Avatar answered Oct 16 '22 23:10

Andreas Florath