Есть ли на месте эквивалент «map» в python? - PullRequest
11 голосов
/ 10 ноября 2010

У меня есть список строк, которые мне нужно очистить.У меня есть метод для их дезинфекции, поэтому я могу просто сделать:

new_list = map(Sanitize, old_list)

, но мне не нужно держать старый список.Это заставило меня задуматься, есть ли на месте эквивалент карты.Достаточно легко написать для него цикл for (или пользовательский метод отображения на месте), но есть ли что-нибудь встроенное?

Ответы [ 4 ]

11 голосов
/ 10 ноября 2010

Ответ прост: нет.

Вопросы формы "существует ли XXX" никогда не имеют прямого ответа, когда ответ нет , поэтому я решил поставитьэто там.

Большинство помощников и встроенных средств itertools работают с общими итераторами.map, filter, списки, for - все они работают на итераторах, не модифицируя исходный контейнер (если есть).

Почему в этой категории нет мутирующих функций?Потому что нет универсального универсального способа присваивать значения контейнерам по отношению к их ключам и значениям.Например, основные итераторы dict (for x in {}) перебирают ключи, а при присвоении dict в качестве параметра для [] используется результат dict.Списки, с другой стороны, перебирают значения , и присваивание использует неявный индекс.Основная согласованность заключается не в том, чтобы предоставлять общие функции, подобные этой, поэтому ничего подобного нет ни в itertools, ни во встроенных функциях.

Они могли бы предоставлять его как методы list и dictно в настоящее время они не делают.Вам просто нужно накатить свой.

5 голосов
/ 10 ноября 2010

Вы должны выполнить цикл:

for i in range(len(old_list)):
    old_list[i] = Sanitize(old_list[i])

Там нет ничего встроенного.

Как предлагается в комментариях: функция по желанию ОП:

def map_in_place(fn, l):
    for i in range(len(l)):
        l[i] = fn(l[i])

map_in_place(Sanitize, old_list)
2 голосов
/ 10 ноября 2010

В конце дня,

old_list = map(Sanitize, old_list)

будет сделано именно то, что вам нужно.

Вы можете возразить, что создание нового объекта списка и сборка мусора старого медленнеечем использование существующего.На практике это почти никогда не должно быть проблемой (выделение как единичного фрагмента памяти вряд ли будет узким местом; возможно, если вы делаете это в цикле или имеете очень длинный список, вы можете попробовать сделать бенчмаркинг, но яеще бы поспорить против вас).Помните, что в любом случае вам придется создавать новые строки с нуля как часть Sanitize, и это будет намного дороже.

Стоит отметить, что, как отмечает mluebke, в наши дни понимание списков считается гораздо более "питоническим", чем map (я полагаю, map не рекомендуется в будущих версиях языка).*

Редактировать: Ах, я вижу, вы пытаетесь редактировать значения аргументов, передаваемых в функцию.Я бы довольно настойчиво утверждал, что это «непифонический» и что вы должны возвращать новый список в качестве одного из возвращаемых значений (помните, что при использовании кортежей вы можете иметь более одного возвращаемого значения).

0 голосов
/ 30 июня 2016

Аналогично использованию this[0] = something, вы также можете указать кусочки:

>>> x = [1, 2, 3, 4]
>>> x[1:3] = [0, 0]
>>> x
[1, 0, 0, 4]

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

>>> x = [1, 2, 3, 4]
>>> x[:] = [4, 5, 6]
>>> x
[4, 5, 6]

Это (как видно выше) способно изменить даже длину списка. Как видно ниже, это действительно изменяет реальный объект, а не переопределяет переменную:

>>> x = [1, 2, 3, 4]
>>> y = x
>>> x[:] = [3, 4]
>>> y
[3, 4]

Это не обязательно должен быть список в правом конце задания. Все, что можно повторить, может быть на этой стороне. На самом деле, вы могли бы даже иметь генератор:

>>> x = ["1", "2", "3", "4"]
>>> x[:] = (int(y) for y in x)
>>> x
[1, 2, 3, 4]

или возврат map() (список в Python 2; объект map в Python 3):

>>> x = ["1", "2", "3", "4"]
>>> x[:] = map(int, x)
...