简体   繁体   English

如何从两个列表中创建一个列表列表

[英]How to make a list of lists from two lists

I am trying to accomplish the following task and failing so far. 我正在尝试完成以下任务,但到目前为止却失败了。 I have two sorted lists of numbers. 我有两个排序的数字列表。 Say

A = [5.8, 6.5, 7.6, 14.5, 18.1, 25.7, 26.4, 30.7, 30.9, 33.6, 38.6, 38.8, 39.2]

B = [9.0, 13.5, 22.5, 32.3 40.6, 43.2, 47.9, 54.2, 60.3, 63.0]

I want to make a list of lists. 我要列出清单。 Each list contains a different value from B and all the values in A between that B-value and the one directly before it in the list. 每个列表包含一个与B不同的值,以及A中该B值与列表中紧邻其前一个值之间的所有值。 The first list just contains everything smaller than the first value in B. 第一个列表仅包含小于B中的第一个值的所有内容。

So in this case the list of lists should start 因此,在这种情况下,列表列表应该开始

[[5.8, 6.5, 7.6, 9.0], [13.5], [14.5, 18.1, 22.5], [25.7, 26.4, 30.7. 30.9, 32.3]....]

I would be happy with numpy code if that is simpler/faster. 如果更简单/更快,我将对numpy代码感到满意。

I tried: 我试过了:

[[*a, b] for b, a in itertools.groupby(A, lambda x: next(filter(lambda y: y >= x, B)))]

but it misses out all the singleton lists and I am not sure how fast it is in any case. 但它会错过所有单例列表,并且我不确定在任何情况下它的速度如何。

I would use two pointers like this, 我会这样使用两个指针,

i = 0
j= 0
ans = [] #contains the lists of lists
while j<len(B):
    to_append = []
    while i<len(A) and A[i]<=B[j]:
         to_append.append(A[i])
         i=i+1
    to_append.append(B[j])
    ans.append(to_append)
    j=j+1

Try now 现在试试

You can use heapq.merge for an O(n+m) solution: 您可以将heapq.merge用于O(n + m)解决方案:

from itertools import chain, repeat
from heapq import merge

[*map(list, map(chain, map(iter, repeat(merge(A,B).__next__), B), zip(B)))]
# [[5.8, 6.5, 7.6, 9.0], [13.5], [14.5, 18.1, 22.5], [25.7, 26.4, 30.7, 30.9, 32.3], [33.6, 38.6, 38.8, 39.2, 40.6], [43.2], [47.9], [54.2], [60.3], [63.0]]

This uses merge to merge A and B in order. 这将使用merge按顺序合并A和B。 Next, the two argument form of iter is used to split at the elements from B. This unfortunately eats the split points, so we reattach them using itertools.chain. 接下来,使用iter的两个参数形式在B的元素处进行拆分。不幸的是,这占用了拆分点,因此我们使用itertools.chain重新附加它们。

you could do, 你可以做的

import numpy as np
A = [5.8, 6.5, 7.6, 14.5, 18.1, 25.7, 26.4, 30.7, 30.9, 33.6, 38.6, 38.8, 39.2]
B = [9.0, 13.5, 22.5, 32.3, 40.6, 43.2, 47.9, 54.2, 60.3, 63.0]
A = np.array(A)
B = np.hstack(([-np.inf], B))
result = [np.r_[np.extract((A>B[i]) & (A<= B[i+1]), A), B[i+1]] for i in range(len(B)-1)]

and if you want just lists, you could do afterwards : 如果只需要列表,则可以执行以下操作:

result = [*map(lambda x : list(x), result),]
print(result)
# [[5.8, 6.5, 7.6, 9.0], [13.5], [14.5, 18.1, 22.5], [25.7, 26.4, 30.7, 30.9, 
# 32.3], [33.6, 38.6, 38.8, 39.2, 40.6], [43.2], [47.9], [54.2], [60.3], [63.0]]

Use np.searchsorted to solve the problem in O(N*logN) time. 使用np.searchsorted解决O(N * logN)时间的问题。 First, find position of elements from B in A. Next, split array A using those postions. 首先,从B中的元素中查找元素的位置。其次,使用这些位置拆分数组A。 Finally create a list of desired properties. 最后创建所需属性的列表。

pos = np.searchsorted(A,B)
chunks = np.split(A, pos)
res = [np.hstack(ab) for ab in zip(chunks,B)]

This will generate the required list of ndarrays which you can convert back to list using ndarray.tolist() method: 这将生成所需的ndarray列表,您可以使用ndarray.tolist()方法将其转换回列表:

res_list = list(map(np.ndarray.tolist, res))

As a purely Numpy-based approach (not that significant tho) you could convert your lists to array and do the following: 作为纯粹基于Numpy的方法(不那么重要),您可以将列表转换为数组,然后执行以下操作:

In [43]: ind = (b[:,None] > a).sum(1)

In [44]: np.split(np.insert(a, ind, b), ind + np.arange(1, ind.size +1))
Out[44]: 
[array([5.8, 6.5, 7.6, 9. ]),
 array([13.5]),
 array([14.5, 18.1, 22.5]),
 array([25.7, 26.4, 30.7, 30.9, 32.3]),
 array([33.6, 38.6, 38.8, 39.2, 40.6]),
 array([43.2]),
 array([47.9]),
 array([54.2]),
 array([60.3]),
 array([63.]),
 array([], dtype=float64)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM