У меня есть два списка, содержащие строки. Я хочу взять каждый элемент в base_list и найти, есть ли совпадение первых 3 символов в любых значениях из custom list. Если есть совпадение, замените исходное значение в base_list на значение из custom_list. Если совпадений нет, сохраните исходное значение.

base_list = ["abc123", "cde123", "efg456", "ghi123"]

custom_list = ["abc321", "efg654"]

Ожидаемый выход:

modified_base_list = ["abc321", "cde123", "efg654", "ghi123"]

В конце концов я также хочу написать этот новый modified_base_list как файл, содержащий элементы, по одному на строку.

Я пробовал:

modified_base_list = []

for custom in custom_list:
    for base in base_list:
        if custom[:3] == base[:3]:
            modified_base_list.append(custom)
        else:
            modified_base_list.append(base)


print(modified_base_list)

with open('newfile.txt', 'w') as f:
    for s in modified_base_list:
        f.write(s)

*** РЕДАКТИРОВАТЬ ВОПРОС для учета списков, которые имеют 15k + строк, чтобы найти более быстрый способ сделать это.

0
Jia Li 9 Янв 2017 в 18:55

4 ответа

Лучший ответ

Вы можете использовать понимание списка, содержащее выражение генератора:

base_list = ["abc123", "cde123", "efg456", "ghi123"]
custom_list = ["abc321", "efg654"] 
modified_base_list = [next((y for y in custom_list if y[:3] == x[:3]), x) for x in base_list]
# ['abc321', 'cde123', 'efg654', 'ghi123']

Обратите внимание, что я предполагаю, что один и тот же 3-символьный префикс встречается несколько раз в custom_list, что вы хотите использовать только первый экземпляр.

0
Chris_Rands 9 Янв 2017 в 16:07

Попробуйте выполнить следующее с filter():

res = []

for i in base_list:
    temp = list(filter(lambda j: j[:3] == i[:3], custom_list))
    if temp:
        res.append('**{}**'.format(temp.pop()))
    else:
        res.append(i)

< Сильный > Вывод :

>>> res
['**abc321**', 'cde123', '**efg654**', 'ghi123']
0
ettanany 9 Янв 2017 в 16:12

Это решение, которое изменяет исходный список, заменяя только те, где существует желаемое совпадение:

>>> base_list = ["abc123", "cde123", "efg456", "ghi123"]
>>> custom_list = ["abc321", "efg654"]
>>> for i, x in enumerate(base_list):
        for test in custom_list:
            if test[:3] == x[:3]:
                base_list[i] = test
                break

>>> base_list
['abc321', 'cde123', 'efg654', 'ghi123']

Конечно, если вы не хотите изменять исходный список, вы можете сначала создать его копию, используя modified_base_list = base_list[:].


Вы также можете следовать своей собственной идее, но в этом случае вы должны убедиться, что вы в основном выполняете итерацию по base_list и не добавляете элементы несколько раз:

modified_base_list = []
for base in base_list:
    found = False
    for custom in custom_list:
        if custom[:3] == base[:3]:
            modified_base_list.append(custom)
            found = True
            break

    if not found:
        modified_base_list.append(base)

Вы также можете использовать for…else здесь вместо этой служебной переменной found:

for base in base_list:
    for custom in custom_list:
        if custom[:3] == base[:3]:
            modified_base_list.append(custom)
            break
    else:
        modified_base_list.append(base)
1
poke 9 Янв 2017 в 16:10

Вы можете использовать комбинацию list comprehension и map для этого:

base_list = ["abc123", "cde123", "efg456", "ghi123"]

custom_list = ["abc321", "efg654"]

smaller_custom = [y[:3] for y in custom_list]

modified_base_list = ["**{}**".format(custom_list[smaller_custom.index(x[:3])]) if x[:3] in smaller_custom else x for x in base_list]
# ['**abc321**', 'cde123', '**efg654**', 'ghi123']

with open('output_data.txt','w') as outfile:
    outfile.write("\n".join(modified_base_list))

Надеюсь, это поможет.

0
Abdou 9 Янв 2017 в 17:26