2017-01-10 1 views
-4

ли какой-нибудь способ, чтобы сделать из этого списка строк:Как группировать файлы по их пути в списке

['/User/someuser/file.py', '/tmp/download/file.zip', '/tmp/download/file2.zip', '/', '/usr/local/bin', '/tmp/file.txt'] 

сделать этот список

[('/tmp/download', ('file.zip', 'file2.zip')), ('/tmp', ('file.txt',)), 
('/User/someuser', ('file.py',)), ('/',()), ('/usr/local/bin',())] 
+4

Можете ли вы показать, что вы пробовали до сих пор? – styvane

+0

Я должен понять это в конвейере, не могу найти способ. –

+0

Если один из этих ответов [обратился к вашей проблеме] (http://stackoverflow.com/help/someone-answers), пожалуйста, рассмотрите [его принятие] (http://meta.stackexchange.com/questions/5234), нажав на галочке/галочке слева от ответа, повернув его зеленым. Это означает, что вопрос был удовлетворен вашим удовлетворением, а также награды [репутации] (http://stackoverflow.com/help/whats-reputation) как вам, так и тому, кто ответил. Как только у вас будет = = 15 очков репутации, вы также можете поддержать ответ, если хотите. Это не обязательно. – MattDMo

ответ

3

Вы можете использовать collections.defaultdict вместе с os.path.split() как:

from collections import defaultdict 
import os 

my_list = ['/User/someuser/file.py', '/tmp/download/file.zip', '/tmp/download/file2.zip', '/', '/usr/local/bin', '/tmp/file.txt'] 
my_dict = defaultdict(list) 

for item in my_list: 
    if os.path.isdir(item): # To check path is a directory 
     _ = my_dict[item] # will set default value as empty list 
    else: 
     path, file = os.path.split(item) 
     my_dict[path].append(file) 

# where `my_dict` is `dict` object holding value: 
# {'/tmp/download': ['file.zip', 'file2.zip'], '/tmp': ['file.txt'], '/usr/local/bin': [], '/': [], '/User/someuser': ['file.py']} 

для того, чтобы преобразовать my_dict в список желаемого формата, сделайте следующее:

>>> my_dict.items() 
[ # Formatted in order to make more readable 
    ('/tmp/download', ['file.zip', 'file2.zip']), 
    ('/tmp', ['file.txt']), 
    ('/usr/local/bin', []), 
    ('/', []), 
    ('/User/someuser', ['file.py']) 
] 
+0

Большое спасибо за помощь –

+1

'/ usr/local/bin' - пустой каталог –

+0

@JoseRicardoBustosM. У вас наверняка есть очень * pythonic глаза *;) Обновлен ответ. –

2

Использование os.path.split разделить имена путей в имя папки и базовое имя. Затем используйте группу itertools.groupby для группировки файлов.

import os 
from itertools import groupby 


l= ['/User/someuser/file.py', '/tmp/download/file.zip', '/tmp/download/file2.zip', '/', '/usr/local/bin', '/tmp/file.txt'] 

print([(k, tuple(i[1] for i in g)) for k, g in groupby(map(os.path.split, sorted(l)), key=lambda x: x[0])]) 

печатает

[('/', ('',)), ('/User/someuser', ('file.py',)), ('/tmp/download', ('file.zip', 'file2.zip')), ('/tmp', ('file.txt',)), ('/usr/local', ('bin',))] 
+0

'groupby',' map', 'sorted' и * list comprehension * для решения однострочного решения - это не очень хорошая идея. Кажется, это сложный комплекс для простой задачи. –

+0

Спасибо большое! –

+0

Это именно то, что мне нужно –

0

Вы можете использовать groupby и os.path

from itertools import groupby 
import os 
L = ['/User/someuser/file.py', '/tmp/download/file.zip', '/tmp/download/file2.zip', '/', '/usr/local/bin', '/tmp/file.txt'] 
#if all files have extention, convert '/usr/local/bin' to '/usr/local/bin/' 
L_fix = [e if os.path.splitext(e)[1] else os.path.join(e,"") for e in L] 
[(k,tuple(map(os.path.basename,v))) for k,v in groupby(L_fix, os.path.dirname)] 

вы получите,

[('/User/someuser', ('file.py',)), 
('/tmp/download', ('file.zip', 'file2.zip')), 
('/', ('',)), 
('/usr/local/bin', ('',)), 
('/tmp', ('file.txt',))] 
+0

Благодарим за помощь –

Смежные вопросы