简体   繁体   中英

Nested for loop (list comprehension) in python; outer loop not looping

I am trying to compare data from columns from two different files. I've attempted to use a for , and now a list comprehension .

The issue is that the outer for loop is not being iterated through, but the inner one is. I've checked individually and iteration is just fine; but once I nest I get this issue. Is there something I missing with this?

import csv

newInv  = csv.reader(open("new.csv", "r"))
origInv = csv.reader(open("old.csv", "r"))

print [ oldrow[5] + " " + newrow[3]  for oldrow in origInv for newrow in newInv ]

Note that in your solution the for loops are nested, so that's why one loop seems to iterate while the other one doesn't seem to.

What you need to use to get one element of both iterators at a time is itertools.izip :

[ oldrow[5] + " " + newrow[3]
for oldrow, newrow in itertools.izip(origInv, newInv)]

The outer is iterated. However, the inner loop is only executed for the first iteration of the outer loop - then the end of newInv has been reached.

Understand that newInv is not a set that you can iterate over multiple times . It is an iterator that you can use only once. Try this (untested):

newInv  = list(csv.reader(open("new.csv", "r")))
origInv = list(csv.reader(open("old.csv", "r")))

which will copy the data into memory and allow you to iterate over multiple times.

There are two things going on here.

1) Your list comprehension has two iterations in it. Conceptually, you are asking to re-iterate over newInv for every oldrow .

2) The reason you don't see every combination of (oldRow, newRow), like you'd expect given the first point, is that a csv.reader is a stream , and thus can only be iterated over once. Each subsequent "iteration" over newInv finds no new items, because they were all "used up" the first time.

To get every combination of (old row, new row), form list s from each csv.reader first (you can pass them directly to the list constructor.

To get one sequence of pair-wise combinations of (old row, new row), zip the two csv.reader s together.

这可能是括号中的一个简单问题。

print [[(expression with i and j) for i in foo] for j in bar]

From the docs

itertools.product(*iterables[, repeat])
Cartesian product of input iterables.

Equivalent to nested for-loops in a generator expression. For example, product(A, B) returns the same as ((x,y) for x in A for y in B).

The nested loops cycle like an odometer with the rightmost element advancing on every iteration. This pattern creates a lexicographic ordering so that if the input's iterables are sorted, the product tuples are emitted in sorted order.

To compute the product of an iterable with itself, specify the number of repetitions with the optional repeat keyword argument. For example, product(A, repeat=4) means the same as product(A, A, A, A).

This function is equivalent to the following code, except that the actual implementation does not build up intermediate results in memory:

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = map(tuple, args) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)

New in version 2.6.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM