views:

1329

answers:

4

<edit> Thanks to everyone who has answered so far. The zip and os.path.join are really helpful. Any suggestions on ways to list the counter in front, without doing something like this:

zip(range(len(files)), files, directories)

</edit>

Hi,

I'm in the process of learning Python, but I come from a background where the following pseudocode is typical:

directories = ['directory_0', 'directory_1', 'directory_2']
files = ['file_a', 'file_b', 'file_c']

for(i = 0; i < directories.length; i++) {
    print (i + 1) + '. ' + directories[i] + '/' + files[i] + '\n'
}

# Output:
# 1. directory_0/file_a
# 2. directory_1/file_b
# 3. directory_2/file_c

In Python, the way I would write the above right now, would be like this:

directories = ['directory_0', 'directory_1', 'directory_2']
files = ['file_a', 'file_b', 'file_c']

for i in range(len(directories)):
    print '%s. %s/%s' % ((i + 1), directories[i], files[i]

# Output:
# 1. directory_0/file_a
# 2. directory_1/file_b
# 3. directory_2/file_c

While reading Dive into Python, Mark Pilgrim says that using for loops for counters is "Visual Basic-style thinking" (Simple Counters). He goes on to show how to use loops with dictionaries, but never really addresses a python solution in regards to how for loop counters are typically used in other languages.

I was hoping somebody could show me how to properly write the above scenario in Python. Is it possible to do it a different way?

If I took out the incrementing line count, is it possible to just match the two lists together using some kind of list comprehension?

For example, if all I wanted from the output was this (no counters, is that possible with list comprehension):

# Output:
# directory_0/file_a
# directory_1/file_b
# directory_2/file_c

Thanks in advance for any help.

+6  A: 

Try this:

directories = ['directory_0', 'directory_1', 'directory_2']
files = ['file_a', 'file_b', 'file_c']

for file, dir in zip(files, directories):
    print dir + '/' + file

To explain, the zip() function takes lists as input and returns a list of "zipped" tuples. so zip([1,2,3,4,5],[a,b,c,d,e]) would return [(1,a),(2,b) and so on.

You can then assign the members of the tuples to variables with the python for <var> in <list> syntax.

There are a million different ways to do what you are asking, but the above uses some more "pythonic" constructs to make the code a lot more readable (IMHO, anyway).

Ryan
Wow, the zip function is great! Any recommendation on how to get the counters in front without doing something like this zip(range(len(files)), files, directories)?
thx for the explanation, +1 for tht
dhaval
+19  A: 
import os.path
for dir, file in zip(directories, files):
    print(os.path.join(dir, file))                      # for directories, files

you can have it as a list comprehension as well, creating list of string with print going after that]

with counter:

for i, (dir, file) in enumerate(zip(directories, files)):
    print(i, os.path.join(dir, file))
SilentGhost
Thanks for the answer! The os.path.join is really helpful. Any recommendation on how to get the counters in front?
A: 

Building on Ryan's answer, you can do:

for fileDir in [dir + '/' + file for dir in directories for file in files]:
    print(fileDir)
Jekke
This gives the cross product of the files and directories (n² lines instead of n).
Ben Blank
Ah. I misread the question and thought that was what he wanted. You are correct.
Jekke
Although it didn't solve the problem, it did give me something to think about - thanks for the response.
A: 

If you want to add a counter to any for loop in Python you can use the enumerate() function:

listA = ["A", "B", "C", "D", "E"]
listB = ["a", "b", "c", "d", "e"]
for i, (a, b) in enumerate(zip(listA, listB)):
    print "%d) %s, %s" % (i, a, b)

gives the output:

0) A, a
1) B, b
2) C, c
3) D, d
4) E, e
KingRadical
as was suggested by the accepted answer
SilentGhost
Sorry, I missed that bit of the accepted answer ;P
KingRadical