Изменить случайное значение списка в любой точке независимо от глубины - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть список, который может быть любой глубины или длины.Под этим я подразумеваю, что у меня может быть такой список:

lst = [1,2,3]

Или:

lst = [[2,233],[[[4,5],[66.33]],[[24,88.65,103,2200.0],[-44.2,-8,5]]], [[[[[[[[5]]]]]]]]]

и то, что я хотел быdo is random изменить одно из этих числовых значений в списке.Я знаю, что мог бы сделать что-то хитроумное, преобразовав список в строку, но, если есть стандартный способ сделать это, будет полезен ответ, касающийся этого!

Редактировать:

Для тех, кто не знает, вы не можете просто случайным образом выбрать любое из этих значений и изменить его (например, добавить 1 к нему), так как список может быть вложенным.Вот пример ввода и вывода, который я пытаюсь получить:

lst = [[2,233],[[[4,5],[66.33]],[[24,88.65,103,2200.0],[-44.2,-8,5]]], [[[[[[[[5]]]]]]]]]
lst = modify(lst,4) # Where 4 is the amount to add to a random number in the list

>lst: [[2,233],[[[4,9],[66.33]],[[24,88.65,103,2200.0],[-44.2,-8,5]]], [[[[[[[[5]]]]]]]]] 
# the fourth number to appear left-to-right in the list 5 has had 4 added to it, ultimately resulting in 9
# this number was randomly selected

Повторный запуск того же кода с обновленным lst:

lst = modify(lst,-2)
>lst: [[2,233],[[[4,9],[66.33]],[[24,86.65,103,2200.0],[-44.2,-8,5]]], [[[[[[[[5]]]]]]]]]
# The seventh number 88.65 has had 2 subtracted from it, to ultimately equal 86.65

1 Ответ

0 голосов
/ 27 февраля 2019

Первая проблема состоит в том, чтобы перебирать список по порядку, независимо от глубины вложения.Вот генератор, который возвращает именно это (вдохновленный этим ответом ):

import functools
import operator

def iter_nested_list(input_list):
    # build index of first level elements
    index_list_to_check = [(i, ) for i in range(len(input_list))]

    while len(index_list_to_check) > 0:
        current_index = index_list_to_check.pop(0)

        # get the element
        elem = functools.reduce(operator.getitem, current_index, input_list)

        if isinstance(elem, list):
            for i in range(len(elem)):
                # this is a list, so we need to check one level deeper
                index_list_to_check.append(current_index + (i, ))
        else:
            # this is not a list, so we yield the index
            yield current_index

Это можно использовать так:

>>> list_1 = [[2,233],[[[4,5],[66.33]],[[24,88.65,103,2200.0],[-44.2,-8,5]]],[[[[[[[[5]]]]]]]]]
>>> iter_nested_list(list_1)
<generator object iter_nested_list at 0x7fdbbc29d990>
>>> list(iter_nested_list(list_1))
[(0, 0), (0, 1), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 0, 2), (1, 1, 0, 3), (1, 1, 1, 0), (1, 1, 1, 1), (1, 1, 1, 2), (2, 0, 0, 0, 0, 0, 0, 0, 0)]

Чтобы получить одинЭлемент из списка, мы можем использовать полученные индексы:

>>> index_list = list(iter_nested_list(list_1))
>>> index = index_list[1]
>>> index
(0, 1)
>>> functools.reduce(operator.getitem, index, input_list)
233

Теперь, чтобы изменить элемент:

def modify(input_list, value_to_add):
    index_list = list(iter_nested_list(list_1))
    index = random.choice(index_list)

    index_base = index[:-1]    # list of all elements from 'index' excluding the last one
    index_elem = index[-1]     # single element, the last of the list 'index'

    # get list that holds the value we randomly selected
    sub_list = functools.reduce(operator.getitem, index_base, input_list)

    # modify value
    sub_list[index_elem] += value_to_add

И вот он в действии:

>>> list_1 = [[2,233],[[[4,5],[66.33]],[[24,88.65,103,2200.0],[-44.2,-8,5]]],[[[[[[[[5]]]]]]]]]
>>> modify(list_1, 5)
>>> list_1
[[2, 233], [[[4, 5], [66.33]], [[24, 88.65, 103, 2200.0], [-44.2, -8, 10]]], [[[[[[[[5]]]]]]]]]
>>> modify(list_1, 5)
>>> list_1
[[2, 233], [[[4, 5], [66.33]], [[24, 88.65, 103, 2205.0], [-44.2, -8, 10]]],  [[[[[[[[5]]]]]]]]]
>>> modify(list_1, 5)
>>> list_1
[[2, 233], [[[4, 5], [66.33]], [[24, 88.65, 103, 2205.0], [-39.2, -8, 10]]], [[[[[[[[5]]]]]]]]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...