Как сделать понимание вложенного списка без создания продукта? - PullRequest
2 голосов
/ 30 марта 2011

В Python я хочу перечислить все файлы в наборе каталогов. Лучшее, что я хотел бы получить - это список. Но самое большее, мне удалось составить вложенный список:

pics = os.path.expanduser('~/Pictures')
all_pics = [(d, os.listdir(d)) for d in os.listdir(pics)]

результат:

[('folder1', ['file1', 'file2', ...]), ('folder2', ['file1', ...]), ...]

что я хочу:

[('folder1' 'file1'), ('folder1', 'file2'), ..., ('folder2', 'file1'), ...]

То, что я хотел бы получить, - это простой простой список, неважно, что (может быть из кортежей), просто чтобы он не имел вложенных объектов, и мне не нужны вложенные циклы в коде, который его анализирует .

Как я могу сделать это со списками? Это дает мне продукт из двух наборов (имена и имена файлов), что неверно:

[(d, f) for f in os.listdir(os.path.join(pics, d)) for d in os.listdir(pics)]

Ответы [ 5 ]

5 голосов
/ 30 марта 2011

Вы ошиблись порядком циклов for. Должно быть

all_pics = [(d, f)
            for d in os.listdir(pics)
            for f in os.listdir(os.path.join(pics, d))]

Сначала самый внешний цикл, последний внутренний цикл.

Интересно, почему вы не получили NameError за d.

4 голосов
/ 30 марта 2011

Использование os.walk - лучшая идея:

all_pics = [(dir,file)
            for dir,sub,files in os.walk(pics) 
            for file in files]

Так почему же это лучшая идея?

  • она работает и с более глубокими деревьями (subdir/subdir/pic.jpg)
  • оно не сломается, если вы поместите файл в ~/Pictures (если вы позвоните os.listdir для файлов, вы получите OSError: [Errno 20] Not a directory)
  • это проще: os.walk делаетдля вас все, что осталось, это отформатировать вывод
1 голос
/ 30 марта 2011

Постижения списков работают как отображение из одного списка в другой.Как указал другой автор, вы можете сделать это, вложив их, но действительно ли вы этого хотите?Вы должны отдавать предпочтение удобочитаемости над всем остальным, во всех большинстве случаев - и я не считаю, что вложенное понимание легко понять.

What is wrong with? It might be marginally slower - but will you notice?

files = []
for d in os.listdir(pics):
    for f in os.listdir(os.path.join(pics, d)):
        files.append((d, f))

Если вы не хотите создавать список до тех пор, пока это не станет абсолютно необходимымВы можете использовать генератор:

def get_file_mapping():
    for d in os.listdir(pics):
        for f in os.listdir(os.path.join(pics, d)):
            yield (d, f)
files = list(get_file_mapping())
0 голосов
/ 30 марта 2011

Вам просто нужно сгладить ваш список вывода:

pics = os.path.expanduser('~/Pictures')
all_pics = reduce(lambda xs,ys: xs+ys, [(d, os.listdir(d)) for d in os.listdir(pics)])
0 голосов
/ 30 марта 2011
l = [ [(d, f) for f in os.listdir(os.path.join(pics, d))] for d in os.listdir(pics) ]
l = sum(l, []) # flatten list of lists => list
...