Как заменить значения на конкретные индексы списка python?

Если у меня есть список:

to_modify = [5,4,3,2,1,0]

А затем объявите два других списка:

indexes = [0,1,3,5]
replacements = [0,0,0,0]

Как я могу взять элементы to_modify качестве индекса для indexes, затем установить соответствующие элементы в to_modify для replacements, то есть после запуска indexes должны быть [0,0,3,0,1,0].

По-видимому, я могу сделать это через цикл for:

for ind in to_modify:
    indexes[to_modify[ind]] = replacements[ind]

Но есть ли другой способ сделать это? Могу я как-то использовать operator.itemgetter?

Ответ 1

Самая большая проблема с вашим кодом заключается в том, что он не читается. Правило кода Python номер один, если оно не читается, никто не будет смотреть на него достаточно долго, чтобы извлечь из него какую-либо полезную информацию. Всегда используйте имена описательных переменных. Почти не поймал ошибку в вашем коде, давайте увидим ее снова с хорошими именами, стиль воспроизведения в замедленном режиме:

to_modify = [5,4,3,2,1,0]
indexes = [0,1,3,5]
replacements = [0,0,0,0]

for index in indexes:
    to_modify[indexes[index]] = replacements[index]
    # to_modify[indexes[index]]
    # indexes[index]
    # Yo dawg, I heard you liked indexes, so I put an index inside your indexes
    # so you can go out of bounds while you go out of bounds.

Как очевидно, когда вы используете имена описательных переменных, вы индексируете список индексов со значениями из себя, что не имеет смысла в этом случае.

Также при повторении через 2 списка параллельно мне нравится использовать функцию zip (или izip, если вы беспокоитесь о потреблении памяти, но я не являюсь одним из этих итерационных пуристов). Поэтому попробуйте это.

for (index, replacement) in zip(indexes, replacements):
    to_modify[index] = replacement

Если ваша проблема работает только со списками номеров, я бы сказал, что у @steabert есть ответ, который вы искали с помощью этого материала. Однако вы не можете использовать последовательности или другие типы данных с переменным размером как элементы массивов numpy, поэтому, если ваша переменная to_modify имеет что-то подобное в ней, вам, вероятно, лучше всего это сделать с циклом for.

Ответ 2

numpy имеет массивы, которые позволяют вам использовать другие списки/массивы в качестве индексов:

import numpy
S=numpy.array(s)
S[a]=m

Ответ 3

Почему не просто:

map(s.__setitem__, a, m)

Ответ 4

Немного медленнее, но читаем, я думаю:

>>> s, l, m
([5, 4, 3, 2, 1, 0], [0, 1, 3, 5], [0, 0, 0, 0])
>>> d = dict(zip(l, m))
>>> d  #dict is better then using two list i think
{0: 0, 1: 0, 3: 0, 5: 0}
>>> [d.get(i, j) for i, j in enumerate(s)]
[0, 0, 3, 0, 1, 0]

Ответ 5

для индекса в a:

Это приведет к тому, что index примет значения элементов a, поэтому использование их в качестве индексов не то, что вы хотите. В Python мы перебираем контейнер, фактически итератизируя его.

"Но подождите", вы говорите: "Для каждого из этих элементов a мне нужно работать с соответствующим элементом m. Как я должен делать это без индексов?"

Simple. Преобразуем a и m в список пар (элемент из a, элемент из m) и итерации по парам. Это легко сделать - просто используйте встроенную библиотечную функцию zip, как показано ниже:

for a_element, m_element in zip(a, m):
  s[a_element] = m_element

Чтобы заставить его работать так, как вы пытались это сделать, вам нужно будет получить список индексов для перебора. Это выполнимо: мы можем использовать range(len(a)), например. Но не делай этого! Это не то, как мы делаем вещи на Python. Фактически прямое повторение того, что вы хотите перебрать, - это прекрасная идея, освобождающая разум.

как насчет operator.itemgetter

Здесь не очень важно. Цель operator.itemgetter состоит в том, чтобы превратить акт индексирования во что-то в функционально-подобную вещь (что мы называем "вызываемым" ), чтобы ее можно было использовать в качестве обратного вызова (например, "ключ" для сортировка или мин/макс). Если бы мы использовали его здесь, нам нужно было бы повторно вызвать его каждый раз через цикл, чтобы создать новый элемент itemget, чтобы мы могли сразу использовать его один раз и выбросить. В контексте это просто занятая работа.

Ответ 6

Вы можете использовать operator.setitem.

from operator import setitem
a = [5, 4, 3, 2, 1, 0]
ell = [0, 1, 3, 5]
m = [0, 0, 0, 0]
for b, c in zip(ell, m):
    setitem(a, b, c)
>>> a
[0, 0, 3, 0, 1, 0]

Является ли это более читабельным или эффективным, чем ваше решение? Я не уверен!

Ответ 7

Вы можете решить это, используя словарь

to_modify = [5,4,3,2,1,0]
indexes = [0,1,3,5]
replacements = [0,0,0,0]

dic = {}
for i in range(len(indexes)):
    dic[indexes[i]]=replacements[i]
print(dic)

for index, item in enumerate(to_modify):
    for i in indexes:
        to_modify[i]=dic[i]
print(to_modify)

Выход будет

{0: 0, 1: 0, 3: 0, 5: 0}
[0, 0, 3, 0, 1, 0]