将python列表投影到现有值上(使用生成器的生成器)

将python列表投影到现有值上(使用生成器的生成器),python,list,Python,List,给定一个常量、一个已排序的浮点列表和一个由两个元素组成的浮点列表 CONST = 1. lst1 = [1.2, 2.4, 3.1] #sorted lst2 = [[2.0, 0.9], [3.1, 1.5], [1.0, 3.0], [2.5, 2.0]] 我为lst1 我需要在[CONST,a]列表中“投影”list2:lst2中成对的第二个值将更改为列表1中最接近的值,成对的第一个值将是相同第二个值的所有第一个值的总和 因此,给出的示例的结果将是: [[6.1, 1.2], [3.5

给定一个常量、一个已排序的浮点列表和一个由两个元素组成的浮点列表

CONST = 1.
lst1 = [1.2, 2.4, 3.1] #sorted
lst2 = [[2.0, 0.9], [3.1, 1.5], [1.0, 3.0], [2.5, 2.0]] 
我为
lst1

我需要在
[CONST,a]
列表中“投影”
list2
:lst2中成对的第二个值将更改为列表1中最接近的值,成对的第一个值将是相同第二个值的所有第一个值的总和

因此,给出的示例的结果将是:

[[6.1, 1.2], [3.5, 2.4], [2.0, 3.1]]
到目前为止,我有一些类似于:

from itertools import groupby
from bisect import bisect
from operator import itemgetter

for t in lst2:
    i = bisect(lst1, t[1])
    bounds = lst1[i-1:i+1] if i else [lst1[0]]
    t[1] = min(bounds, key=lambda x: abs(x-t[1]))

lst2 += [[CONST, a] for a in lst1]
lst2 = sorted(lst2, key=itemgetter(1))
res = [[sum([t[0] for t in group]), keys] for keys, group in groupby(lst2, itemgetter(1))]

但是列表(特别是
lst1
)可能很长(1e5+),我觉得我可以在那里有更好的效率。有什么想法吗?

由于排序控制着运行时间,所以很难加快速度,但这里有一个版本不需要使用lst1。但是,它会在lst1中迭代:

sorted_lst2 = sorted(lst2, key=itemgetter(1))
i = 0
res = []
k = 0
while i + 1 < len(lst1):
    before = lst1[i]
    const = CONST
    while i + 1 < len(lst1) and before == lst1[i + 1]:
        const += CONST
        i += 1
    after = lst1[i + 1]
    mid = before + (after - before) / 2
    sum_before = 0
    while k < len(sorted_lst2) and sorted_lst2[k][1] <= mid:
        sum_before += sorted_lst2[k][0]
        k += 1
    res.append([const + sum_before, before])
    i += 1
sum_before = 0
while k < len(sorted_lst2):
    sum_before += sorted_lst2[k][0]
    k += 1
res.append([CONST + sum_before, lst1[-1]])
sorted_lst2=sorted(lst2,key=itemgetter(1))
i=0
res=[]
k=0
当i+1当k
CONST = 1.
lst1 = [1.2, 2.4, 3.1] #sorted
lst2 = [[2.0, 0.9], [3.1, 1.5], [1.0, 3.0], [2.5, 2.0]]

def gen_generator(lst1):
    #Create iterators to form consecutive pairs
    it1_1, it1_2 = iter(lst1), islice(lst1+[float('inf')], 1, None)
    #Create iterator over items to insert and initialize p
    gen_generator.it2 = iter(sorted(lst2, key=itemgetter(1)))
    gen_generator.p=next(gen_generator.it2)
    for t1, t2 in zip(it1_1, it1_2):
        #Calculate the mid point of the pair t1, t2
        sup = (t1+t2)/2 if t2 != float('inf') else float('inf')
        #Create a generator for each item in lst1
        def generator():
            #All the previously inserted items have disappeared
            #So yield any p such that p[1] < sup
            while gen_generator.p is not None and gen_generator.p[1] < sup:
                yield gen_generator.p[0]
                #Move to next or None
                gen_generator.p = next(gen_generator.it2, None)
            #Add the constant
            yield CONST
        yield generator

res = [[sum(gen()), t] for gen, t in zip(gen_generator(lst1), lst1)]
return res
CONST=1。
lst1=[1.2,2.4,3.1]#排序
lst2=[[2.0,0.9]、[3.1,1.5]、[1.0,3.0]、[2.5,2.0]]
def发电机(lst1):
#创建迭代器以形成连续对
it1_1,it1_2=iter(lst1),islice(lst1+[float('inf')],1,无)
#在项上创建迭代器以插入和初始化p
gen_generator.it2=iter(已排序(lst2,key=itemgetter(1)))
gen_generator.p=下一个(gen_generator.it2)
对于拉链中的t1、t2(it1_1、it1_2):
#计算对t1、t2的中点
sup=(t1+t2)/2如果t2!=浮动('inf')否则浮动('inf'))
#为lst1中的每个项目创建一个生成器
def生成器():
#以前插入的所有项目都已消失
#所以产生任何p,使得p[1]
从现在起两周后,您需要引入一些修改,您需要多长时间才能理解此代码?Imho,从这个角度来看,您的原始代码,问题中的代码,是更好的…这就是注释的目的。我不介意抽象。