Python: нахождение файлов с соответствием расширениям или расширениям с соответствием именам в списке

Предположим, что у меня есть список имен файлов: [exia.gundam, dynames.gundam, kyrios.gundam, virtue.gundam], или [exia.frame, exia.head, exia.swords, exia.legs, exia.arms, exia.pilot, exia.gn_drive, lockon_stratos.data, tieria_erde.data, ribbons_almark.data, otherstuff.dada].

В одном повторении я хотел бы иметь весь *.gundam или *.data файлы, тогда как на другом я хотел бы сгруппировать exia.* файлы. Каков самый легкий способ сделать это помимо итерации через список и помещения каждого элемента в словаре?

Вот то, что я имел в виду:

def matching_names(files):
    '''
    extracts files with repeated names from a list

    Keyword arguments:
    files - list of filenames

    Returns: Dictionary
    '''

    nameDict = {}
    for file in files:
        filename = file.partition('.')
        if filename[0] not in nameDict:
            nameDict[filename[0]] = []
        nameDict[filename[0]].append(filename[2])

    matchingDict = {}
    for key in nameDict.keys():
        if len(nameDict[key]) > 1:
            matchingDict[key] = nameDict[key] 
    return matchingDict

Ну, принятие, я должен использовать это, там простой способ инвертировать его и иметь расширение файла как ключ вместо имени?

1
задан SilentGhost 4 July 2010 в 05:00
поделиться

3 ответа

В моей первой версии, похоже, я неверно истолковал ваш вопрос. Итак, если у меня все правильно, вы пытаетесь обработать список файлов, чтобы вы могли легко получить доступ ко всем именам файлов с заданным расширением или ко всем именам файлов с заданной базой («база» - это часть перед период)?

Если это так, я бы порекомендовал этот способ:

from itertools import groupby

def group_by_name(filenames):
    '''Puts the filenames in the given iterable into a dictionary where
    the key is the first component of the filename and the value is
    a list of the filenames with that component.'''
    keyfunc = lambda f: f.split('.', 1)[0]
    return dict( (k, list(g)) for k,g in groupby(
               sorted(filenames, key=keyfunc), key=keyfunc
           ) )

Например, учитывая список

>>> test_data = [
...   exia.frame, exia.head, exia.swords, exia.legs,
...   exia.arms, exia.pilot, exia.gn_drive, lockon_stratos.data,
...   tieria_erde.data, ribbons_almark.data, otherstuff.dada
... ]

, эта функция выдала бы

>>> group_by_name(test_data)
{'exia': ['exia.arms', 'exia.frame', 'exia.gn_drive', 'exia.head',
          'exia.legs', 'exia.pilot', 'exia.swords'],
 'lockon_stratos': ['lockon_stratos.data'],
 'otherstuff': ['otherstuff.dada'],
 'ribbons_almark': ['ribbons_almark.data'],
 'tieria_erde': ['tieria_erde.data']}

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

def group_by_extension(filenames):
    '''Puts the filenames in the given iterable into a dictionary where
    the key is the last component of the filename and the value is
    a list of the filenames with that extension.'''
    keyfunc = lambda f: f.split('.', 1)[1]
    return dict( (k, list(g)) for k,g in groupby(
               sorted(filenames, key=keyfunc), key=keyfunc
           ) )

Единственная разница в строке keyfunc = ... , где я изменил ключ с 0 на 1. Пример:

>>> group_by_extension(test_data)
{'arms': ['exia.arms'],
 'dada': ['otherstuff.dada'],
 'data': ['lockon_stratos.data', 'ribbons_almark.data', 'tieria_erde.data'],
 'frame': ['exia.frame'],
 'gn_drive': ['exia.gn_drive'],
 'head': ['exia.head'],
 'legs': ['exia.legs'],
 'pilot': ['exia.pilot'],
 'swords': ['exia.swords']}

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

from collections import defaultdict
def group_by_both(filenames):
    '''Puts the filenames in the given iterable into two dictionaries,
    where in the first, the key is the first component of the filename,
    and in the second, the key is the last component of the filename.
    The values in each dictionary are lists of the filenames with that
    base or extension.'''
    by_name = defaultdict(list)
    by_ext = defaultdict(list)
    for f in filenames:
        name, ext = f.split('.', 1)
        by_name[name] += [f]
        by_ext[ext] += [f]
    return by_name, by_ext
2
ответ дан 2 September 2019 в 23:19
поделиться

Я не уверен, что полностью понял, что вы хотите сделать, но если я правильно понимаю, может сработать что-то вроде этого:

from collections import defaultdict
files_by_extension = defaultdict(list)

for f in files:
    files_by_extension[ f.split('.')[1] ].append(f)

Это создание хэша по ключу расширения файла и его заполнение путем итерации по списку за один проход.

0
ответ дан 2 September 2019 в 23:19
поделиться

Предположим, например, что вы хотите получить список списков имен файлов, сгруппированных по расширению или корневому имени:

import os.path
import itertools as it

def files_grouped_by(filenames, use_extension=True):
    def ky(fn): return os.path.splitext(fn)[use_extension]
    return [list(g) for _, g in it.groupby(sorted(filenames, key=ky), ky)]

Теперь files_grouped_by (filenames, False) вернет список списков, сгруппированных по rootname, а если второй аргумент True или отсутствует, группировка будет по расширению.

Если вы хотите вместо этого использовать dict, где ключи являются либо корневыми именами, либо расширениями, а значения - соответствующими списками имен файлов, подход очень похож:

import os.path
import itertools as it

def dict_files_grouped_by(filenames, use_extension=True):
    def ky(fn): return os.path.splitext(fn)[use_extension]
    return dict((k, list(g)) 
                for k, g in it.groupby(sorted(filenames, key=ky), ky)]
0
ответ дан 2 September 2019 в 23:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: