Как поменять значение в составном списке

a = [('123',), ('456',), [['12313', '2662'], ['52525', ['4234', ['009999']]]]],[('45235626t2',)]

for i in a:
    for k in i:
        for y in k:
            if y == '123':
                new = y.replace(y, '000')
                a[0][0] = new

Хочу поменять ('123',) на ('000',) но при этом вообще меняется вся структура списка, как поменять так чтоб поменялось только '123' в кортеже?


Ответы (2 шт):

Автор решения: Andy Pavlov

И так. Можно пойти многими путями, к примеру, самый относительно простой и чуть более сложный.

Вариант с помощью рекурсии обойти список и поменять значения:

def list_replace(lst: list, value_search, value_replace):
    res = []
    for item in lst:  # Итерируем входной список
        if isinstance(item, (list, set, tuple)):
            res.append(list_replace(item, value_search, value_replace))  # На этом уровне уходим в список, сет, кортеж глубже
        else:
            res.append(item if item != value_search else value_replace)  # добавляем значение в результирующий список, если совпадает с искомым значением, то меняем его
    return type(lst)(res)

a_repl = list_replace(a, '123', '000')

Через библиотеку json с помощью json.dumps() дампим а в строку. В строке делаем замену через replace(). Дальше с помощью json.loads() грузим обратно в переменную.

import json

a = [[('123',), ('456',), [['12313', '2662'], ['52525', ['4234', ['009999']]]]],[('45235626t2',)]]
a_dump = json.dumps(a)
a_replace = a_dump.replace('"123"', '"000"')  # если убрать двойные кавычки внутри, то поменяет все строки, в которых есть 123
a_from_json = json.loads(a_replace)

Вывод:

# список а-исходный
[[('123',), ('456',), [['12313', '2662'], ['52525', ['4234', ['009999']]]]], [('45235626t2',)]]
# список после json
[[['000'], ['456'], [['12313', '2662'], ['52525', ['4234', ['009999']]]]], [['45235626t2']]]
# список после рекурсии
[[('000',), ('456',), [['12313', '2662'], ['52525', ['4234', ['009999']]]]], [('45235626t2',)]] 

Если у нас переменная а кортеж, то с ним тоже вариант с рекурсией работает:

a = [('123',), ('456',), [['12313', '2662'], ['52525', ['4234', ['009999']]]]],[('45235626t2',)]

Вывод:

([('000',), ('456',), [['12313', '2662'], ['52525', ['4234', ['009999']]]]], [('45235626t2',)])
→ Ссылка
Автор решения: CrazyElf

Ну вот примерно так. Рекурсивно перебираем, и если находим кортеж с первым элементом '123', то подменяем его. Нужно учесть, что кортеж неизменен, поэтому менять его можно только целиком. И по этой же причине работать это будет только внутри списка. Кстати, переменная a у вас кортеж из двух элементов, внутри которых уже списки. Поэтому вроде и можно было бы списочное сокращение применить, но вот этот кортеж наружный не даёт.

a = [('123',), ('456',), [['12313', '2662'], ['52525', ['4234', ['009999']]]]],[('45235626t2',)]

def change_val(items):
    for i in range(len(items)):
        item = items[i]
        if isinstance(item, tuple) and item[0] == '123':
            items[i] = ('000', *item[1:])
        else:
            if isinstance(item, (list,tuple)):
                change_val(item)

change_val(a)    
print(a)

Вывод:

([('000',), ('456',), [['12313', '2662'], ['52525', ['4234', ['009999']]]]], [('45235626t2',)])

В общем, если возможен вариант "кортеж в кортеже" и подменять нужно будет в нём, то код надо будет ещё переделывать, всё будет ещё сложнее.

→ Ссылка