Python:查找列表元素之间的差异

2025-01-14 08:50:00
admin
原创
99
摘要:问题描述:给定一个数字列表,如何找出每个 ( i) 个元素与其 ( i+1) 个元素之间的差异?lambda使用表达式或者列表推导是否更好?例如: 给定一个列表t=[1,3,6,...],目标是找到一个列表,v=[2,3,...]因为3-1=2,,6-3=3等等。解决方案 1:>>> t [...

问题描述:

给定一个数字列表,如何找出每个 ( i) 个元素与其 ( i+1) 个元素之间的差异?

lambda使用表达式或者列表推导是否更好?

例如:

给定一个列表t=[1,3,6,...],目标是找到一个列表,v=[2,3,...]因为3-1=2,,6-3=3等等。


解决方案 1:

>>> t
[1, 3, 6]
>>> [j-i for i, j in zip(t[:-1], t[1:])]  # or use itertools.izip in py2k
[2, 3]

解决方案 2:

其他答案都是正确的,但是如果你正在做数值工作,你可能需要考虑numpy。使用numpy,答案是:

v = numpy.diff(t)

解决方案 3:

如果你不想使用numpynor zip,你可以使用以下解决方案:

>>> t = [1, 3, 6]
>>> v = [t[i+1]-t[i] for i in range(len(t)-1)]
>>> v
[2, 3]

解决方案 4:

从 开始Python 3.10,使用新pairwise功能,可以滑动元素对,从而映射到滚动对上:

from itertools import pairwise

[y-x for (x, y) in pairwise([1, 3, 6, 7])]
# [2, 3, 1]

中间结果是:

pairwise([1, 3, 6, 7])
# [(1, 3), (3, 6), (6, 7)]

解决方案 5:

您可以使用itertools.teezip来有效地构建结果:

from itertools import tee
# python2 only:
#from itertools import izip as zip

def differences(seq):
    iterable, copied = tee(seq)
    next(copied)
    for x, y in zip(iterable, copied):
        yield y - x

或者使用itertools.islice

from itertools import islice

def differences(seq):
    nexts = islice(seq, 1, None)
    for x, y in zip(seq, nexts):
        yield y - x

您也可以避免使用该itertools模块:

def differences(seq):
    iterable = iter(seq)
    prev = next(iterable)
    for element in iterable:
        yield element - prev
        prev = element

如果您不需要存储所有结果并支持无限可迭代,则所有这些解决方案都在恒定空间中工作。


以下是一些解决方案的微基准测试:

In [12]: L = range(10**6)

In [13]: from collections import deque
In [15]: %timeit deque(differences_tee(L), maxlen=0)
10 loops, best of 3: 122 ms per loop

In [16]: %timeit deque(differences_islice(L), maxlen=0)
10 loops, best of 3: 127 ms per loop

In [17]: %timeit deque(differences_no_it(L), maxlen=0)
10 loops, best of 3: 89.9 ms per loop

其他建议的解决方案如下:

In [18]: %timeit [x[1] - x[0] for x in zip(L[1:], L)]
10 loops, best of 3: 163 ms per loop

In [19]: %timeit [L[i+1]-L[i] for i in range(len(L)-1)]
1 loops, best of 3: 395 ms per loop

In [20]: import numpy as np

In [21]: %timeit np.diff(L)
1 loops, best of 3: 479 ms per loop

In [35]: %%timeit
    ...: res = []
    ...: for i in range(len(L) - 1):
    ...:     res.append(L[i+1] - L[i])
    ...: 
1 loops, best of 3: 234 ms per loop

注意:

  • zip(L[1:], L)相当于,zip(L[1:], L[:-1])因为zip已经在最短输入上终止,但是它避免了整个的复制L

  • 通过索引访问单个元素非常慢,因为每个索引访问都是 python 中的方法调用

  • numpy.diff,因为它必须先将 转换listndarray。显然,如果你从 开始,ndarray快得多

In [22]: arr = np.array(L)

In [23]: %timeit np.diff(arr)
100 loops, best of 3: 3.02 ms per loop

解决方案 6:

我建议使用

v = np.diff(t)

这很简单并且易于阅读。

但如果你想要和那么v相同的长度t

v = np.diff([t[0]] + t) # for python 3.x

或者

v = np.diff(t + [t[-1]])

仅供参考:这仅适用于列表。

对于 numpy 数组

v = np.diff(np.append(t[0], t))

解决方案 7:

使用:=Python 3.8+ 中提供的海象运算符:

>>> t = [1, 3, 6]
>>> prev = t[0]; [-prev + (prev := x) for x in t[1:]]
[2, 3]

解决方案 8:

功能性方法:

>>> import operator
>>> a = [1,3,5,7,11,13,17,21]
>>> map(operator.sub, a[1:], a[:-1])
[2, 2, 2, 4, 2, 4, 4]

使用生成器:

>>> import operator, itertools
>>> g1,g2 = itertools.tee((x*x for x in xrange(5)),2)
>>> list(itertools.imap(operator.sub, itertools.islice(g1,1,None), g2))
[1, 3, 5, 7]

使用索引:

>>> [a[i+1]-a[i] for i in xrange(len(a)-1)]
[2, 2, 2, 4, 2, 4, 4]

解决方案 9:

好的。我想我找到了正确的解决方案:

v = [x[0]-x[1] for x in zip(t[1:],t[:-1])]

解决方案 10:

我怀疑这就是 numpy diff 命令所做的,但为了完整性,您可以简单地对子向量进行区分:

from numpy import array as a
a(x[1:])-a(x[:-1])

此外,我想针对该问题的概括添加以下解决方案:

具有周期性边界的解决方案

有时使用数值积分时,您会希望对具有周期性边界条件的列表进行差分(因此第一个元素计算与最后一个元素的差。在这种情况下,numpy.roll 函数很有用:

v-np.roll(v,1)

以零开头的解决方案

另一个numpy解决方案(仅出于完整性考虑)是使用

numpy.ediff1d(v)

它与 numpy.diff 一样工作,但只适用于向量(它将输入数组展平)。它提供了在结果向量前面或后面添加数字的功能。这在处理累积字段时很有用,这些字段通常是气象变量中的通量(例如雨水、潜热等),因为您希望结果列表的长度与输入变量的长度相同,并且第一个条目保持不变。

然后你会写

np.ediff1d(v,to_begin=v[0])

当然,您也可以使用 np.diff 命令执行此操作,但在这种情况下,您需要使用 prepend 关键字将零添加到系列的前面:

np.diff(v,prepend=0.0) 

所有上述解决方案都返回与输入长度相同的向量。

解决方案 11:

您还可以使用以下方法将差异转换为易于阅读的转换矩阵

v = t.reshape((c,r)).T - t.T

其中c= 列表中的项目数和r= 1,因为列表基本上是一个向量或一维数组。

解决方案 12:

我的方式

>>>v = [1,2,3,4,5]
>>>[v[i] - v[i-1] for i, value in enumerate(v[1:], 1)]
[1, 1, 1, 1]
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用