[英]Projecting python list onto existing values (with generator of generators)
給定一個常量,一個排序的浮點數列表和一個包含 2 個元素的浮點數列表,
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]
對
我需要在[CONST,a]
的列表上“投影” list2
: lst2
對的第二個值將更改為 list1 中最接近的值,該對的第一個值將是所有第一個值的總和對於相同的第二個值。
所以給出的例子的結果是:
[[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]])
我想我找到了一種有趣的方法:生成器的生成器! Python 很棒! 這大約是之前代碼的兩倍。
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.