Как случайным образом заменить определенный элемент во вложенном списке? - PullRequest
0 голосов
/ 21 октября 2018

У меня есть список списков.Как создать функцию, которая случайным образом заменяет экземпляр 10 другим числом?

lst = [ [10, 100, 10 ], [10, 1000, 10], [100, 100000, 100], [10, 10, 0] ]

Вот мой код.Я могу только получить плоский список вместо вложенного списка.Как получить вложенный список, и есть ли более эффективный способ?

import random

def random_replace10(num, lst): # replaces 10 with num
    indexes = []
    flattened = [num for row in lst for num in row]
    for ind, ele in enumerate(flattened):
        if ele == 10:
            indexes.append(ind)

    random_index = random.sample(indexes, 1)[0]
    flattened[random_index] = num
    return flattened           #Returns a flattened list instead of a nested list.


print(random_replace10(2, lst))

>>> [ [10, 100, 2 ], [10, 1000, 10], [100, 100000, 100], [10, 10, 0] ]

print(random_replace10(91, lst))

>>> [ [10, 100, 2 ], [10, 1000, 10], [100, 100000, 100], [91, 10, 0] ]

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Вы можете сделать что-то вроде ниже

import random

lst = [[10, 100, 10], [10, 1000, 10], [100, 100000, 100], [10, 10, 0]]


def random_replace10(num, lst):
    ten_index = []
    for i, item in enumerate(lst):
        for j, inner_item in enumerate(item):
            if inner_item == 10:
                ten_index.append((i, j))

    i, j = random.choice(ten_index)
    lst[i][j] = num
    print(lst)
0 голосов
/ 21 октября 2018

Сначала вам нужно выяснить, сколько у вас значений 10, а затем выбрать, какое из них заменить опцией random.randrange().Я использовал itertools.count(), чтобы счетчик хода соответствовал выбранному экземпляру:

from itertools import count
import random


def random_replace10(num, lst):
    selected = random.randrange(sum(sum(1 for i in sub if i == 10) for sub in lst))
    counter = count()
    return [
        [num if i == 10 and next(counter) == selected else i for i in sub] 
        for sub in lst
    ]

Это заменяет ровно одно значение 10 на num, не больше, не меньше, и создает новый список.Старый список остается нетронутым.

Вы также можете сделать замену на месте, но в этом случае я бы вернул None (так же, как это сделали бы другие методы мутации в list, такие как list.append() и т. Д.).В этом случае сначала запишите местоположения значений 10, используйте random.choice(), чтобы выбрать одно из этих мест:

import random

def random_replace10_inplace(num, lst):
    locations = [(i, j) for i, sub in enumerate(lst) for j, v in enumerate(sub) if v == 10]
    outer, inner = random.choice(locations)
    lst[outer][inner] = num

Демонстрация первой версии:

>>> lst = [[10, 100, 10], [10, 1000, 10], [100, 100000, 100], [10, 10, 0]]
>>> random_replace10(2, lst)
[[10, 100, 10], [10, 1000, 2], [100, 100000, 100], [10, 10, 0]]
>>> random_replace10(2, lst)
[[10, 100, 10], [10, 1000, 10], [100, 100000, 100], [10, 2, 0]]
>>> random_replace10(91, lst)
[[10, 100, 91], [10, 1000, 10], [100, 100000, 100], [10, 10, 0]]
>>> random_replace10(91, lst)
[[10, 100, 10], [10, 1000, 91], [100, 100000, 100], [10, 10, 0]]

и версии на месте:

>>> lst = [[10, 100, 10], [10, 1000, 10], [100, 100000, 100], [10, 10, 0]]
>>> random_replace10_inplace(2, lst)
>>> lst
[[10, 100, 10], [10, 1000, 2], [100, 100000, 100], [10, 10, 0]]
>>> random_replace10_inplace(2, lst)
>>> lst
[[10, 100, 10], [2, 1000, 2], [100, 100000, 100], [10, 10, 0]]
>>> random_replace10_inplace(91, lst)
>>> lst
[[10, 100, 10], [2, 1000, 2], [100, 100000, 100], [91, 10, 0]]
>>> random_replace10_inplace(91, lst)
>>> lst
[[91, 100, 10], [2, 1000, 2], [100, 100000, 100], [91, 10, 0]]
...