Какова цель функции zip (как в Python или C # 4.0)? - PullRequest
12 голосов
/ 12 марта 2010

Кто-то спросил Как сделать zip-код Python в C #? ...

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

Ответы [ 7 ]

11 голосов
/ 12 марта 2010

Вариант использования:

>>> fields = ["id", "name", "location"]
>>> values = ["13", "bill", "redmond"]
>>> dict(zip(fields, values))
{'location': 'redmond', 'id': '13', 'name': 'bill'}

Попробуйте сделать это без почтового индекса ...

11 голосов
/ 12 марта 2010

Кто-то на самом деле недавно задал вопрос , на который я ответил методом расширения Zip, так что это очевидно важно для некоторых людей. ;)

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

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

Это может звучать как простая сортировка / группировка / объединение в SQL Server (например), но на самом деле это действительно сложно сделать эффективно. Во-первых, временные метки могут не совпадать точно, но вам не нужны различия в несколько миллисекунд, поэтому вам придется сгенерировать суррогатный ключ / номер строки и группу для этого - и, конечно, суррогатный номер строки не более чем время index , которое у вас уже было . Молния проста, быстра и бесконечно распараллеливаема.

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

Одной из причин, по которой вам может показаться не очень полезным, является то, что в .NET / C # 3.5 нет кортежей. В C # 4 действительно есть кортежи , и когда вы работаете с кортежами, действительно, архивирование является фундаментальной операцией, поскольку порядок строго соблюдается.

10 голосов
/ 12 марта 2010

zip полезен, если вы хотите выполнять итерации по нескольким итерациям одновременно, что является довольно распространенным сценарием в Python.

Один из реальных сценариев, где zip мне пригодился, это если у вас есть массив M by N, и вы хотите смотреть на столбцы, а не на строки. Например:

>>> five_by_two = ((0, 1), (1, 2), (2, 3), (3, 4), (4, 5))
>>> two_by_five = tuple(zip(*five_by_two))
>>> two_by_five
((0, 1, 2, 3, 4), (1, 2, 3, 4, 5))
9 голосов
/ 12 марта 2010

Вот типичный пример использования zip:

x = [1,2,3,4,5]
y = [6,7,8,9,0]

for a,b in zip(x,y):
    print a, b

Что бы вывести:

1 6
2 7
3 8
4 9
5 0
7 голосов
/ 12 марта 2010

Позволяет обрабатывать последовательности параллельно, а не последовательно или вложенно. Там ... так много применений, что они в настоящее время избегают меня.

3 голосов
/ 12 марта 2010

Это удобно в разных местах. Мой любимый из http://norvig.com/python-iaq.html, транспонирует матрицу:

>>> x = [ [1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]]
>>> zip(*x)
[(1, 6, 11), (2, 7, 12), (3, 8, 13), (4, 9, 14), (5, 10, 15)]
2 голосов
/ 12 марта 2010

Вот случай, когда я использовал zip() для полезного эффекта, в классе Python для сравнения номеров версий:

class Version(object):

    # ... snip ...

    def get_tuple(self):
        return (self.major, self.minor, self.revision)

    def compare(self, other):
        def comp(a, b):
            if a == '*' or b == '*':
                return 0
            elif a == b:
                return 0
            elif a < b:
                return -1
            else:
                return 1
        return tuple(comp(a, b) for a, b in zip(self.get_tuple(), Version(other).get_tuple()))

    def is_compatible(self, other):
        tup = self.compare(other)
        return (tup[0] == 0 and tup[1] == 0)

    def __eq__(self, other):
        return all(x == 0 for x in self.compare(other))

    def __ne__(self, other):
        return any(x != 0 for x in self.compare(other))

    def __lt__(self, other):
        for x in self.compare(other):
            if x < 0:
                return True
            elif x > 0:
                return False
        return False

    def __gt__(self, other):
        for x in self.compare(other):
            if x > 0:
                return True
            elif x < 0:
                return False
        return False

Я думаю, zip() в сочетании с all() и any() делает реализацию оператора сравнения особенно ясной и элегантной. Конечно, это можно было бы сделать без zip(), но то же самое можно сказать практически о любой языковой функции.

...