Python 如何按范围对列表元素进行分组/计数

Python 如何按范围对列表元素进行分组/计数,python,list,dictionary,Python,List,Dictionary,如果我的x列表和y列表是: x = [10,20,30] y = [1,2,3,15,22,27] 我希望返回值是一个字典,它的元素计数小于x值: { 10:3, 20:1, 30:2, } 我有一个非常大的列表,所以我希望有一个更好的方法来完成它,而不需要一个缓慢的嵌套for循环。我已经看过了集合。计数器和itertools,它们似乎都没有提供分组的方式。是否有可以执行此操作的内置计数器?您可以使用对分模块和集合。计数器: >>> import b

如果我的x列表和y列表是:

x = [10,20,30]
y = [1,2,3,15,22,27]
我希望返回值是一个字典,它的元素计数小于x值:

{
    10:3,
    20:1,
    30:2,
}

我有一个非常大的列表,所以我希望有一个更好的方法来完成它,而不需要一个缓慢的嵌套for循环。我已经看过了集合。计数器和itertools,它们似乎都没有提供分组的方式。是否有可以执行此操作的内置计数器?

您可以使用
对分
模块和
集合。计数器

>>> import bisect
>>> from collections import Counter
>>> Counter(x[bisect.bisect_left(x, item)] for item in y)
Counter({10: 3, 30: 2, 20: 1})

如果您愿意使用numpy,基本上您需要的是柱状图:

x = [10,20,30]
y = [1,2,3,15,22,27]

np.histogram(y,bins=[0]+x)
#(array([3, 1, 2]), array([ 0, 10, 20, 30]))
要使这成为一条格言:

b = np.histogram(y,bins=[0]+x)[0]
d = { k:v for k,v in zip(x, b)}
对于短列表,这不值得,但如果您的列表很长,则可能是:

In [292]: y = np.random.randint(0, 30, 1000)

In [293]: %%timeit
   .....: b = np.histogram(y, bins=[0]+x)[0]
   .....: d = { k:v for k,v in zip(x, b)}
   .....: 
1000 loops, best of 3: 185 µs per loop

In [294]: y = list(y)

In [295]: timeit Counter(x[bisect.bisect_left(x, item)] for item in y)
100 loops, best of 3: 3.84 ms per loop

In [311]: timeit dict(zip(x, [[n_y for n_y in y if n_y < n_x] for n_x in x]))
100 loops, best of 3: 3.75 ms per loop
[292]中的
y=np.random.randint(0,30,1000)
在[293]中:%%timeit
…b=np.直方图(y,bin=[0]+x)[0]
…d={k:v代表k,v在zip(x,b)}
.....: 
1000个回路,最好为3个:每个回路185µs
在[294]中:y=列表(y)
In[295]:timeit计数器(y中项目的x[对分对分左(x,项目)])
100圈,最佳3圈:每圈3.84毫秒
In[311]:timeit dict(zip(x,[[n_y表示n_y,如果n_y
简短回答:

dict(zip(x, [[n_y for n_y in y if n_y < n_x] for n_x in x]))
dict(zip(x,[[n_y表示n_y,如果n_y
长答案

首先,我们需要迭代y来检查哪个成员小于某个值。如果我们花10英镑,我们会得到:

>>> [n_y for n_y in y if n_y < 10]
[1, 2, 3]
>>>[如果n\u y<10,则n\u y表示n\u y在y中]
[1, 2, 3]
然后我们需要将“10”设为一个看起来像x的变量:

>>> [[n_y for n_y in y if n_y < n_x] for n_x in x]
[[1, 2, 3], [1, 2, 3, 15], [1, 2, 3, 15, 22, 27]]
>>>[[n_y表示n_y,如果n_y
最后,我们需要将这个结果与原始x的结果相加。以下是zip方便的时候:

>>> zip(x, [[n_y for n_y in y if n_y < n_x] for n_x in x])
[(10, [1, 2, 3]), (20, [1, 2, 3, 15]), (30, [1, 2, 3, 15, 22, 27])]
>>>zip(x,[[n_y表示n_y,如果n_y
这是一个元组列表,因此我们应该对其强制转换dict以获得最终结果:

>>> dict(zip(x, [[n_y for n_y in y if n_y < n_x] for n_x in x]))
{10: [1, 2, 3], 20: [1, 2, 3, 15], 30: [1, 2, 3, 15, 22, 27]}
dict(zip(x,[[n_y表示n_y,如果n_y
如果
x
中的值之间的步长始终为
10
,我会这样做:

>>> y = [1,2,3,15,22,27]
>>> step = 10
>>> from collections import Counter
>>> Counter(n - n%step + step for n in y)
Counter({10: 3, 30: 2, 20: 1})

我最初的目标是制作柱状图,因此非常感谢您的回答。选择更一般的答案作为问题的最佳答案,但我肯定也会使用这个!