Zip python чем заменить

Есть ли функция, которая может заменить функцию «zip» в Python?

Но, похоже, zip создал новый список. Во многих случаях, которые я хочу, это всего лишь пара данных (a [i], b [i]), я вообще не хочу «zip». В С# мы можем сделать итератор, чтобы получить пару данных из a и b, поэтому мы могли бы избежать создания нового «zip» списка. Как насчет питона?

Не к вашему вопросу, но я думаю, что есть более ясные способы написать [x[0] + x[1] for x in zip(a,b)] . [sum(x) for x in zip(a,b)] яснее, но медленнее, а [x+y for x,y in zip(a,b)] яснее и быстрее. (Конечно, ясность в глазах смотрящего.)

4 ответа

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

>>> from itertools import izip >>> a = [1,2,3,4,5] >>> b = [5,4,3,2,1] >>> c = izip(a, b) >>> c >>> for x, y in c: . print x, y . 1 5 2 4 3 3 4 2 5 1 

Обратите внимание, что в Python-3.x отсутствует izip() , zip() возвращает итератор.

Возможно, стоит отметить, что в python3.x itertools.izip исчезает, а обычный zip возвращает итеративный объект, а не list .

Вам не нужна функция сама по себе, просто используйте выражение генератора:

a = [1,2,3,4,5] b = [5,4,3,2,1] for pair in ((a[i], b[i]) for i in xrange(min(len(a), len(b)))): print pair 

-0. Вы отвечаете на вопрос, но это и безобразно, и не нужно, поскольку существует itertools.izip . Мне нравится, что вы упомянули выражения генератора.

Читайте также:  Sql server java maven

Генератор для фиксированного или переменного числа итераций

Вы также можете создать свой собственный генератор в Python:

def mygen(a, b): """generator yielding values from two iterables""" aiter = iter(a) biter = iter(b) while True: yield aiter.next(), biter.next() def dyngen(*iterables): """generator for yielding list from dynamic number of iterables""" iterables = map(iter, iterables) while True: yield map(next, iterables) if __name__ == "__main__": a = [1,2,3,4,5] b = [5,4,3,2,1] c = ["a", "b", "c", "d", "e"] gen = mygen(a, b) print gen.next() print gen.next() print gen.next() print gen.next() print gen.next() print "dyngen" gen = dyngen(a, b, c) print gen.next() print gen.next() print gen.next() print gen.next() print gen.next() 

Вызов из командной строки:

$ python myzip.py (1, 5) (2, 4) (3, 3) (4, 2) (5, 1) dyngen [1, 5, 'a'] [2, 4, 'b'] [3, 3, 'c'] [4, 2, 'd'] [5, 1, 'e'] 

Источник

zip с аналогом в питоне?

Не могли бы вы объяснить, как это работает? Есть много людей, знающих Python, но только некоторые из них знают Хаскелл достаточно хорошо.

@Tadeck: zipWith похож на map , за исключением того, что он пересекает два списка параллельно, применяя функцию к соответствующим элементам из каждого списка. Если один список длиннее, дополнительные элементы игнорируются. Например, zipWith (*) [1, 2, 3] [7, 8] == [7, 16] .

6 ответов

Вы можете создать свой, если хотите, но в Python мы в основном делаем

list_c = [ f(a,b) for (a,b) in zip(list_a,list_b) ] 

поскольку Python не является функционально функциональным. Это просто помогает поддерживать несколько удобных идиом.

Если вы хотите быть немного более элегантным, вы можете сделать [f(*list_c) for list_c in zip(list_a, list_b)] — используя оператор splat чтобы распаковать кортеж, а не указывать его дважды. Это также имеет то преимущество, что вы можете просто добавить больше аргументов в функцию zip, и она будет работать успешно, если вам нужно.

Обратите внимание, что если вы используете Python 2.x, приведенный выше код не ленив: zip() создаст список, который будет использоваться один раз. В Python 2.x вы можете использовать itertools.izip() для ленивых вычислений; в Python 3 вы получаете ленивую оценку с помощью встроенного zip() .

@steveha, но имейте в виду, что это не очень лениво (в смысле ближайшего Python) в смысле Haskell, даже используя izip вместо zip , так как он дается как понимание списка, а не как выражение генератора.

@lvc lvc, я прекрасно понимаю, что приведенный выше код показывает понимание списка. Продолжайте и прочитайте то, что я написал снова: zip() создаст список, который используется один раз. Чтобы избежать создания и последующего уничтожения этого списка, вы можете использовать itertools.izip() . Я не знаю Haskell, но кажется вероятным, что даже в Haskell, если желаемым выходным продуктом является список, в какой-то момент ленивый код будет преобразован в список. Я предложил написать ленивый код для случайной работы на пути к созданию окончательного, действительно желаемого списка.

@steveha, что вы сказали, что «вышеприведенный код не ленив» в 2.x. В 3.x он не ленив: он сразу выдаст весь список вывода. В 3.x не будет также построить промежуточное значение вывода из zip , так что в этом смысле может быть немного больше лени, но код в целом не является ленивым , независимо от того , какой версии Python вы с помощью. Для этого, как сказал @lvc, вам понадобится выражение генератора. (А также izip чтобы избежать материализации всего промежуточного списка при доступе к первому элементу.)

@benw, ты хочешь сказать, что я неправильно использовал слово «ленивый» в связи с тем, что не создавал и не уничтожал промежуточный список? Я думал, что мое использование термина «ленивый» было правильным: значения не вычисляются, пока они нам не нужны, и в этом случае «когда они нам нужны» — это когда они попадают в список, который является желаемым конечным результатом. ru.wikipedia.org/wiki/Lazy_evaluation Все сказанное выше, я действительно не очень чувствую это, и если для вас важно, чтобы слово «ленивый» никогда не появлялось при создании списка, тогда я прошу прощения за оскорбляя ваши чувства.

Источник

Разбираемся, как работает встроенная функция zip в Python, и пишем свою реализацию с помощью list comprehension

Обложка: Разбираемся, как работает встроенная функция zip в Python, и пишем свою реализацию с помощью list comprehension

Многие слышали о функции zip в Python, а кто-то даже регулярно ей пользуется. Сегодня мы (из интереса и для общего развития) опишем, как можно реализовать её самому с помощью list comprehensions.

Для начала поясню, что вообще делает функция zip, для тех, кто с ней раньше не сталкивался:

>>> s = 'abc' >>> t = (10, 20, 30) >>> zip(s,t) [('a', 10), ('b', 20), ('c', 30)]

То есть функция берёт на вход несколько списков и создаёт из них список (в Python 3 создаётся не list, а специальный zip-объект) кортежей, такой, что первый элемент полученного списка содержит кортеж из первых элементов всех списков-аргументов. Таким образом, если ей передать три списка, то она отработает следующим образом:

>>> s = 'abc' >>> t = (10, 20, 30) >>> u = (-5, -10, -15) >>> list(zip(s,t,u)) [('a', 10, -5), ('b', 20, -10), ('c', 30, -15)]

В общем-то, функция отработает даже для одного iterable-объекта, результатом будет последовательность из кортежей, в каждом из которых будет по одному элементу. Но это, пожалуй, не самый распространенный способ применения zip. Я часто использую zip, например, для создания словарей:

>>> names = ['Tom', 'Dick', 'Harry'] >>> ages = [50, 35, 60] >>> dict(zip(names, ages))

Это весьма удобно, не находите? Каждый раз, когда я рассказываю о zip на своих уроках, у меня спрашивают о том, что будет, если в функцию передать массивы разной длины. Ответ простой — победит более короткий:

>>> s = 'abc' >>> t = (10, 20, 30, 40) >>> list(zip(s,t)) [('a', 10), ('b', 20), ('c', 30)] 

Однако, если вам необходимо, чтобы для каждого из элементов более длинного массива в результирующем списке был создан кортеж из одного элемента, вы можете использовать zip_longest из пакета itertools.

Есть одна возможность в Python, которая мне нравится даже больше, чем zip. Это списковое включение (англ. list comprehension). Именно поэтому, когда один из студентов недавно спросил меня, можем ли мы реализовать zip сами с помощью списковых включений, я просто не смог устоять.

Как же нам этого добиться? Начнём с первого, что приходит на ум:

[(s[i], t[i]) # создаём кортеж из двух элементов for i in range(len(s))] # для индексов от 0 до len(s) - 1

В общем-то всё! Это работает. Но есть несколько моментов, которые всё же стоит доработать в этом методе.

Во-первых, оригинальная функция могла работать с массивами разной длины. Поэтому вместо range(len(s)) нам стоит использовать range(len(x)) , где x — наиболее короткая последовательность. Для этого достаточно поместить все последовательности в один список, отсортировать этот список по длине элементов и выяснить длину элемента, оказавшегося под нулевым индексом:

>>> s = 'abcd' >>> t = (10, 20, 30) >>> sorted((s,t), key=len) [(10, 20, 30), 'abcd']

Совмещаем это с предыдущим кодом:

>>> s = 'abcd' >>> t = (10, 20, 30) >>> sorted((s,t), key=len) [(10, 20, 30), 'abcd']

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

>>> def shortest_sequence_range(*args): return range(len(sorted(args, key=len)[0])) >>> [(s[i], t[i]) for i in shortest_sequence_range(s,t) ]

Что осталось теперь? Как уже говорилось выше, Python 3 создаёт не список, а специальный zip-объект, возвращая итератор от него. Это сделано для того, чтобы код не ломался при обработке исключительно длинных последовательностей. Это можно реализовать, но уже не с помощью спискового включения (которое всегда возвращает список), а с помощью генератора. К счастью, для этого достаточно поменять квадратные скобки на круглые:

>>> def shortest_sequence_range(*args): return range(len(sorted(args, key=len)[0])) >>> g = ((s[i], t[i]) for i in shortest_sequence_range(s,t) ) >>> for item in g: print(item) ('a', 10) ('b', 20) ('c', 30) 

Готово! Мы реализовали свой полностью рабочий zip. Вы можете потренироваться и самостоятельно подумать, как ещё можно улучшить этот алгоритм.

Что думаете?

Устроили «сайт знакомств» из найма.В место того чтобы понять что приходящие на собесодования Степашки по большей части интроверты и адаптироваться — лезут в душу со страными вопросами которые Степашек пугают.И упорно пилят гайды как понравится HRюшам.Детсад а не профессионализм.Причем программист в принципе вне круга коллег и общаться то уметь не обязан(а внутри пусть хоть как модемы пиликают).Общаться с кандидатом должен ументь именно HR. Иначе это не HR а редиска.

Ребят, тут собрались ноунеймы которые не работают ни на одном языке, но пишут свое очень важное мнение в комментариях. Лучше проходите мимо и не читайте их. Ах да, учите go и устройтесь в яндекс)

Как вы собираетесь искать хороших сотрудников, если (в большинстве компаний) честных кандидатов отметают даже не пригласив на техническое собеседование?Если умение лгать является обязательным, чтобы устроиться к вам на работу, то не удивляйтесь что «сложно найти хорошего сотрудника».Я знаю о чем говорю. В нашей компании для продвижения программистов на аутсорс есть целая отдельная команда, которая полностью специализируется на «продаже сотрудников». Это люди, которые пристально изучают хотелки чсв hr-ов, пишут «идеальные» резюме и отвечают на все вопросы так, «как надо». А программист приходит только на техническое собеседование в конце.Хорошие сотрудники (как правило) не станут накручивать себе 20 лет стажа, рассказывать про мотивацию «не ради денег», отвечать на глупые вопросы про квадратные люки и прочую ерунду.Вам нужно не учить людей в интернете «как правильно отвечать на наши вопросы, чтобы вы у нас прошли собес», а мыслить шире и заниматься реальным поиском толковых специалистов, которые не обязаны иметь топовые софт-скилы.В противном случае — получайте «идеальные» резюме, написанные по единому шаблону и котов в мешке. И не забудьте пожаловаться что «сложно найти хорошего сотрудника».

Источник

Оцените статью