Кто-то спросил, Как сделать zip Python в C#?...
... который приводит меня спрашивать, что такое хороший zip? В каких сценариях мне нужно это? Это является действительно столь основополагающим, что мне нужно это в библиотеке базовых классов?
Кто-то недавно действительно задал здесь вопрос , на который я ответил с помощью метода расширения Zip
, так что он, очевидно, важен для некоторых людей. ;)
На самом деле, это довольно важная операция для математических алгоритмов - матрицы, аппроксимация кривой, интерполяция, распознавание образов и тому подобное. Также очень важно в инженерных приложениях, таких как цифровая обработка сигналов, где большая часть того, что вы делаете, объединяете несколько сигналов или применяете к ним линейные преобразования - оба основаны на индексе выборки, следовательно, zip его. Сжатие двух последовательностей намного быстрее, чем их сортировка и объединение на основе некоторого ключа, особенно если вы заранее знаете, что последовательности имеют одинаковое количество элементов и находятся в одном порядке.
Я не могу вдаваться в подробности из-за моей нынешней работы, но, вообще говоря, это также ценно для данных телеметрии - промышленных, научных и тому подобных. Часто у вас будут временные последовательности данных, поступающие из сотен или тысяч точек - параллельных источников - и вам потребуется агрегировать, но горизонтально , по устройствам, а не во времени. В конце концов, вам нужна другая временная последовательность, но с суммой, средней или какой-либо другой совокупностью всех отдельных точек.
Это может звучать как простая сортировка / группировка / соединение в SQL Server (например), но на самом деле это действительно сложно сделать таким способом эффективно.Во-первых, временные метки могут не совпадать точно, но вас не волнуют различия в несколько миллисекунд, поэтому вам придется сгенерировать суррогатный ключ / номер строки и группу на этом - и, конечно же, номер суррогатной строки это не что иное, как временной индекс , который у вас уже был . Архивирование - это просто, быстро и с возможностью неограниченного распараллеливания.
Не знаю, могу ли я назвать это основополагающим , но это важно . Я тоже не очень часто использую метод Обратный
, но к тому же я рад, что мне не приходится писать его самому в тех редких случаях, когда он мне действительно нужен.
Одна из причин, по которой это может показаться вам бесполезным сейчас, заключается в том, что .NET / C # 3.5 не имеет кортежей. В C # 4 есть кортежи , и когда вы работаете с кортежами, архивирование действительно является фундаментальной операцией, потому что порядок строго соблюдается.
Это удобно в разных местах. Мой любимый, из 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)]
Вот типичный вариант использования 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
Пример использования:
>>> fields = ["id", "name", "location"]
>>> values = ["13", "bill", "redmond"]
>>> dict(zip(fields, values))
{'location': 'redmond', 'id': '13', 'name': 'bill'}
Попробуйте сделать это без zip ...
Вот случай, когда я использовал 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 ()
, но тогда то же самое можно было бы сказать практически о любой языковой функции.
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))
Позволяет обрабатывать последовательности параллельно, а не последовательно или вложенно. Там... так много применений для него, что они в настоящее время ускользают от меня.