有人问如何在C#中进行Python的zip?...
...这让我问,zip 有什么好处?在什么场景下我需要这个?它真的如此基础以至于我需要在基类库中使用它吗?
最近有人在这里问了一个问题,我用
Zip
扩展方法回答了,所以这对于一些人来说显然很重要。 ;)
实际上,对于数学算法来说,这是一个相当重要的操作——矩阵、曲线拟合、插值、模式识别等。在数字信号处理等工程应用中也非常重要,其中您所做的大部分工作是组合多个信号或对其应用线性变换 - 两者都基于样本索引,因此将其压缩。压缩两个序列比根据某个键对它们进行排序和连接要快得多,尤其是当您事先知道序列具有相同数量的元素并且顺序相同时。
由于我目前的工作,我无法在这里详细说明,但总的来说,这对于遥测数据也很有价值——工业、科学等。通常,您会拥有来自数百或数千个点(并行源)的数据时间序列,并且您需要通过设备(而不是随着时间的推移)进行聚合,但是是“水平”聚合。最后,您想要另一个时间序列,但具有所有单独点的总和或平均值或其他聚合。这听起来像是 SQL Server 中的简单排序/分组/连接(例如),但实际上很难以这种方式高效地完成。一方面,时间戳可能不完全匹配,但您不关心几毫秒的差异,因此您最终必须生成代理键/行号并对其进行分组 - 当然,还有代理行号无非就是你已经拥有的时间
索引。压缩简单、快速且可无限并行。
我不知道是否可以称其为“基础”,但它是“重要”。我也不经常使用 Reverse
方法,但出于同样的原因,我很高兴在我确实需要它的罕见情况下,我不必继续自己编写它。
它现在对您来说似乎没那么有用的原因之一是 .NET/C# 3.5 没有元组。 C# 4 确实有元组,当您使用元组时,压缩确实是一个基本操作,因为顺序是严格执行的。
一个用例:
>>> fields = ["id", "name", "location"]
>>> values = ["13", "bill", "redmond"]
>>> dict(zip(fields, values))
{'location': 'redmond', 'id': '13', 'name': 'bill'}
尝试在没有拉链的情况下执行此操作...
zip 很有用,这是 Python 中相当常见的场景。
zip 对我来说派上用场的一个现实场景是,如果您有一个 M × 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))
它允许您并行处理序列,而不是顺序或嵌套。它有......如此多的用途,以至于我目前无法理解它们。
这是 zip 的常见用例:
哪个会输出:
在不同的地方都很方便。我最喜欢的是来自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)]
这是我在 Python 类中使用 zip()
来比较版本号的情况:
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()
也可以完成,但几乎任何语言功能都可以这样说。