Python 比较两个不同的列表

Python 比较两个不同的列表,python,list,Python,List,我有两个不同长度的列表。示例-- 及 (当然E2的元素数比E1多)。现在我想比较E1列表和E2,找出最接近E1中每个元素的值,比如在本例中E1中的1.3最接近E2中的1.1699。类似地,我想对E1中的所有其他元素执行此操作。。。因此,如果我在E2中形成一个新的列表E3,它将包含与E1完全相似的元素数量和最接近E1元素的值。我该怎么做?感谢您的帮助。快速脏版: E3 = [min(E2, key=lambda x: abs(x-i)) for i in E1] 对于E1中的每个元素,它根据与E

我有两个不同长度的列表。示例--


(当然E2的元素数比E1多)。现在我想比较E1列表和E2,找出最接近E1中每个元素的值,比如在本例中E1中的1.3最接近E2中的1.1699。类似地,我想对E1中的所有其他元素执行此操作。。。因此,如果我在E2中形成一个新的列表E3,它将包含与E1完全相似的元素数量和最接近E1元素的值。我该怎么做?感谢您的帮助。

快速脏版:

E3 = [min(E2, key=lambda x: abs(x-i)) for i in E1]
对于
E1
中的每个元素,它根据与
E1
元素的绝对距离查找
E2
的最小元素

请注意,此列表将包含重复项。例如,对于您的示例,它返回:

[1.0, 1.1699, 1.1699, 1.1699, 1.1699]
因为1.1699最接近
E1
中的所有较大值


线性时间,但更复杂的排序列表解决方案:

E3 = []
p2 = 0
for e1 in E1:
    while p2 < len(E2) - 1 and abs(E2[p2] - e1) > abs(E2[p2+1] - e1):
        p2 += 1
    E3.append(E2[p2])
E3=[]
p2=0
对于e1中的e1:
而p2abs(E2[p2+1]-e1):
p2+=1
E3.追加(E2[p2])

让我向您介绍一个最奇妙的Python模块,
对分

import bisect
def find_nearest(refsort, pt):
    loc = bisect.bisect_left(refsort, pt)
    if loc >= len(refsort)-1:
        # Value greater than all elements of refsort
        return refsort[-1]
    d1 = pt - refsort[i]
    d2 = refsort[i+1] - pt
    if d1 < d2:
        return refsort[i]
    else:
        return refsort[i+1]

def replace_with_nearest(ptlist, reflist):
    ''' Replace every point in ptlist with the nearest value from reflist '''
    refsort = sorted(reflist) # omit if you know reflist is sorted
    return [find_nearest(refsort, pt) for pt in ptlist]

E3 = replace_with_nearest(E1, E2)
导入对分 def find_最近(参考排序,pt): loc=对分。左对分(参考排序,pt) 如果loc>=len(参考排序)-1: #值大于refsort的所有元素 返回refsort[-1] d1=pt-refsort[i] d2=参考排序[i+1]-pt 如果d1
bisect
使用经典的数组对分技术,在
O(logn)
时间中查找小于给定输入的最大数组元素,假设数组已排序。我们使用它来定位两个值,这两个值比
E2
的每个元素都要小和大

这在O(n log k)时间内运行,其中
n
是E2的长度,
k
是E1的长度(假设n>k)。请注意,E2不需要排序。

def最近(num,lst):
def closest(num, lst):
   ret = lst[0]
   dist = abs(lst[0]-num)
   for n in lst:
      if abs(n-num) < dist:
         dist = abs(n-num)
         ret = n
   return ret

e1 = [1.0,1.3,1.69,2.1970,2.8561]
e2 = [1.00,1.04,1.08,1.1249,1.1699]
e3 = [closest(n, e2) for n in e1]
print(e3)
ret=lst[0] dist=abs(lst[0]-num) 对于lst中的n: 如果abs(n-num)
[1.0, 1.1699, 1.1699, 1.1699, 1.1699]
你说的最接近是指差异最小的地方?列表是否已排序?这确实会受益于两个输入的精确样本和所需输出的精确样本。有助于清除您定义为“最接近”的内容。@Burhan Khalid列表已排序。最接近意味着差异最小。这比使用
sorted
而不是
min
的版本要好,但仍然比解决问题所需的速度慢得多。如果对输入进行排序,我们可以在线性时间内通过对输入进行单次传递来解决问题。如果输入未排序,我们可以在线性时间内对其排序,然后应用相同的算法。@user2357112,是的,这不是特别有效。为排序列表添加了线性时间版本。谢谢!但是用字典而不是列表会发生什么呢?key=lambda也可以在字典中使用吗?如果可能的话,如何使用?@user3724647,使用dict,您可以根据数字的不同选择“keys()”或
values()
,并使用该列表。这在O(n*m)时间(二次型)内运行,速度不是特别快。@nneonno,没有参数。如果性能是关键,你的答案就是我想要的。我想你可能把
E1
E2
搞混了。是的,是的。让我来解决这个问题。
import bisect
def find_nearest(refsort, pt):
    loc = bisect.bisect_left(refsort, pt)
    if loc >= len(refsort)-1:
        # Value greater than all elements of refsort
        return refsort[-1]
    d1 = pt - refsort[i]
    d2 = refsort[i+1] - pt
    if d1 < d2:
        return refsort[i]
    else:
        return refsort[i+1]

def replace_with_nearest(ptlist, reflist):
    ''' Replace every point in ptlist with the nearest value from reflist '''
    refsort = sorted(reflist) # omit if you know reflist is sorted
    return [find_nearest(refsort, pt) for pt in ptlist]

E3 = replace_with_nearest(E1, E2)
def closest(num, lst):
   ret = lst[0]
   dist = abs(lst[0]-num)
   for n in lst:
      if abs(n-num) < dist:
         dist = abs(n-num)
         ret = n
   return ret

e1 = [1.0,1.3,1.69,2.1970,2.8561]
e2 = [1.00,1.04,1.08,1.1249,1.1699]
e3 = [closest(n, e2) for n in e1]
print(e3)
[1.0, 1.1699, 1.1699, 1.1699, 1.1699]