Kane Blueriver
Kane Blueriver

Reputation: 4268

How could I rewrite this for loop in list comprehensions

I got a "for loop" like this:

for dirctory in dirs:
    for item in os.walk(dirctory):
        for i in item[2]:
            i = os.path.join(item[0], i)
            if is_image(i):
                images.append(i)

And I tried to rewrite it into list comprehensions, I tried this:

images.extend(filter(is_image, [item[0]+i for i in item[2] for item in os.walk(dirctory)]))

It says UnboundLocalError: local variable 'item' referenced before assignment

So I tried this:

images.extend(filter(is_image, [(item[0]+i for i in item[2]) for item in os.walk(dirctory)]))

It says TypeError: coercing to Unicode: need string or buffer, generator found

I use Python 2.7.4 in OS X.

Upvotes: 3

Views: 608

Answers (3)

thefourtheye
thefourtheye

Reputation: 239663

def check_image(directory, file_name):
    file_name = os.path.join(directory, file_name)
    return is_image(file_name), file_name

[full_path
     for current_dir in dirs
     for parent_dir, _, files in os.walk(current_dir)
     for current_file in files
     for isimage, full_path in [check_image(parent_dir, current_file)]
         if isimage]

The check_image function is there to avoid applying os.path.join twice.

Upvotes: 1

volcano
volcano

Reputation: 3582

Here is how it may be done (it is not exactly what I tested)

[os.path.join(path+fname)  for path, _, files in os.walk('some_folder') 
 for fname in files if os.image(os.path.join([path,fname]))]

but - if you pay attention - you have to join path twice in this solution, so straightforward nested loop may be more efficient

EDIT:

In my example I was looking for Python files by extension, so in that case list comprehension did not suffer from double joining of path/file name

Upvotes: 0

Deelaka
Deelaka

Reputation: 13721

Try this:

[os.path.join(item[0], i) for directory in dirs for item in os.walk(dirctory) for i in item[2] if is_image(os.path.join(item[0], i))]

Upvotes: 1

Related Questions