Какова цель функции zip (как в Python или C# 4.0)?

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

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

13
задан Community 23 May 2017 в 11:45
поделиться

7 ответов

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

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

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

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

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

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

11
ответ дан 1 December 2019 в 17:31
поделиться

Это удобно в разных местах. Мой любимый, из 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)]
3
ответ дан 1 December 2019 в 17:31
поделиться

Вот типичный вариант использования 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
9
ответ дан 1 December 2019 в 17:31
поделиться

Пример использования:

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

Попробуйте сделать это без zip ...

12
ответ дан 1 December 2019 в 17:31
поделиться

Вот случай, когда я использовал 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 () , но тогда то же самое можно было бы сказать практически о любой языковой функции.

2
ответ дан 1 December 2019 в 17:31
поделиться

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))
10
ответ дан 1 December 2019 в 17:31
поделиться

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

7
ответ дан 1 December 2019 в 17:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: