Найти файлы с одинаковой начальной частью имени в двух папках

Я использовал listdir читать файлы в двух папках:

from os import listdir 
list_1 = [file for file in listdir("./folder1/") if file.endswith(".csv")]
list_2 = [file for file in listdir("./folder2/") if file.endswith(".json")]

и теперь у меня есть два списка:

list_1 = ['12_a1_pp.csv', '32_a3_pp.csv', '45_a17_pp.csv', '81_a123_pp.csv']
list_2 = ['12_a1.json', '32_a3.json', '61_a54.json']

Я хочу найти соответствующие два подсписка, содержащие те файлы, чья начальная часть имени совпадает. Другими словами:

list_1b = ['12_a1_pp.csv', '32_a3_pp.csv']
list_2b = ['12_a1.json', '32_a3.json']

Как я могу это сделать?

PS обратите внимание, что listdir часть может не иметь значения, чтобы ответить на вопрос. Я только включил его, потому что если результат listdir гарантированно будет в алфавитном порядке, тогда это может помочь в обход двух списков. Конечно, в этом простом примере списки короткие, но в реальном случае они содержат сотни файлов.

4 ответа

Решение

Более питонический подход будет использовать & (пересечение) оператор для множеств:

common = set(x[:-7] for x in list_1) & set(x[:5] for x in list_2)
list_1b = [x + '_pp.csv' for x in common]
list_2b = [x + '.json' for x in common]

РЕДАКТИРОВАТЬ: Если вам нужно разделить по определенному символу (см. Комментарий) для каждого списка, вот обновленная версия (поиск последнего "_" в списке_1 и поиск последнего "." В списке_2):

common = set(x[:x.rindex('_')] for x in list_1) & set(x[:x.rindex('.')] for x in list_2)

Это один из способов использования словарного понимания и set.intersection,

list_1 = ['12_a1_pp.csv', '32_a3_pp.csv', '45_a17_pp.csv', '81_a123_pp.csv']
list_2 = ['12_a1.json', '32_a3.json', '61_a54.json']

start_1 = {k: '_'.join(k.split('_')[:-1]) for k in list_1}
start_2 = {k: k.split('.')[0] for k in list_2}

start_intersect = set(start_1.values()) & set(start_2.values())

list_1b = [k for k, v in start_1.items() if v in start_intersect]
list_2b = [k for k, v in start_2.items() if v in start_intersect]

Этот метод работает одинаково хорошо, если у вас есть имена файлов, заканчивающиеся на "_XY.csv" для любого "XY". Он опирается на формат имени файла, а не на отдельные буквы.

list_1 = ['12_a1_pp.csv', '32_a3_pp.csv', '45_a17_pp.csv', '81_a123_pp.csv']
list_2 = ['12_a1.json', '32_a3.json', '61_a54.json']

list_1_C = [i.split(".")[0].replace("_pp", "") for i in list_1]     #Check List
list_2_C = [i.split(".")[0] for i in list_2]                        #Check List

print([list_1[i] for i, v in enumerate(list_1_C) if v in list_2_C])
print([list_2[i] for i, v in enumerate(list_2_C) if v in list_1_C])

Выход:

['12_a1_pp.csv', '32_a3_pp.csv']
['12_a1.json', '32_a3.json']

Это просто, когда вы думаете об этом, вот так:

list_1 = ['12_a1_pp.csv', '32_a3_pp.csv', '45_a17_pp.csv', '81_a123_pp.csv']
list_2 = ['12_a1.json', '32_a3.json', '61_a54.json']
starters = [eachfile.partition(".")[0] for eachfile in list2]
 for eachelement in starters:
    for eachfile in list_1:
       if eachfile.startswith(eachelement):
          list_1b.append(eachfile)
          list_2b.append(eachelement+".json")

Кроме того, если вы хотите конкретно для этого случая:

collective_set_1 = { each.replace("_pp.csv","") for each in list_1}
collective_set_2 = { each.replace(".json","") for each in list_2}
intersection = collective_set_1.intersection(collective_set2)
list_1b = [ each+"_pp.csv" for each in intersection ]
list_2b = [ each+".json" for each in intersection ]
Другие вопросы по тегам