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

у меня есть список, скажем

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

и у меня есть еще 2 списка, скажем

a = [0,1,3,5]; m = [0,0,0,0]

то, что я хочу взять a's элементы как индекс к s, затем установите соответствующие элементы в a to m, то есть после запуска,s должно быть [0,0,3,0,1,0].

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

for index in a:
    s[a[index]] = m[index]

но мне интересно, есть ли другой способ сделать это? как насчет оператора?itemgetter ?

6 ответов


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

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 списка параллельно мне нравится использовать


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

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

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

map(s.__setitem__, a, m)

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

>>> 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]

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

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

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

простой. Мы transform a и m в список пар (элемент из a, элемент из m)и перебирать пары. Что легко сделать-просто используйте встроенную функцию библиотеки zip следующим образом:

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

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

насчет оператора.itemgetter

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


можно использовать 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]

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