例如,如果我们的源列表是:
input = [1, 2, 3, 4, 5, 6, 7, 8, 9, ... ]
我需要这样的事情:
output = {1:[1], 2:[2,3], 3:[4,5,6], 4:[7,8,9,...], ...}
我尝试这样,但这不能正常工作:
groups = {}
N = 1
group = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for i in range(0, len(group)-1):
groups.update({N:group[i:i+N]})
N+=1
答案 0 :(得分:5)
为了完整起见,您还可以编写一个适用于任何可迭代的版本:
template <class Type>
int bstree<Type>::count(treeNode* sroot){
int ret = 0;
if ( sroot )
{
ret = sroot->count;
ret += count(sroot->left);
ret += count(sroot->right);
}
return ret;
}
答案 1 :(得分:3)
你可以使用一个字典理解,但首先你需要找到一个合适的索引范围,你可以根据它们分割你的元素!为此目的,您可以使用一个简单的数学公式,即1 ... n的序列之和为n*(n+1)/2
,因此在这种情况下n*(n+1)/2=len(l)
并且通过求解方程,您可以实现{{1}与n
:
一些例子:
(1+math.sqrt(1+8*len(l)))/2)
由于>>> l=[23,12,33,42,5,6,7,8,39,10,11,102]
>>> ind=range(1,int((1+math.sqrt(1+8*len(l)))/2))
>>> {i:l[sum(ind[:i-1]):sum(ind[:i-1])+i] for i in ind}
{1: [23], 2: [12, 33], 3: [42, 5, 6], 4: [7, 8, 39, 10]}
的长度不是5,所以在这种情况下n将为4!但在下面它涵盖了所有元素:
11,102
作为一种更好的方法,您只需计算一次>>> l=[23,12,33,42,5,6,7,8,39,10,11,102,4,0,5]
>>> ind=range(1,int((1+math.sqrt(1+8*len(l)))/2))
>>> {i:l[sum(ind[:i-1]):sum(ind[:i-1])+i] for i in ind}
{1: [23], 2: [12, 33], 3: [42, 5, 6], 4: [7, 8, 39, 10], 5: [11, 102, 4, 0, 5]}
:
sum(ind[:i-1])
Last Note 正如您在第一个示例中所看到的,如果这些解决方案的编号与相应的长度不匹配,则此解决方案不会保留最后的元素。如果你想保留最后的元素你可以使用其他答案,这是很好的东西!
答案 2 :(得分:3)
与Jon的方法类似:
from itertools import islice
it = iter(l)
d = {k: v for k,v in ((i,list(islice(it, i))) for i in range(1, len(l))) if v}
print(d)
{1: [1], 2: [2, 3], 3: [4, 5, 6], 4: [7, 8, 9, 10]}
或者使用takewhile和itemgetter:
from itertools import islice,takewhile
from operator import itemgetter
it = iter(l)
d = {k: v for k,v in takewhile(itemgetter(1),((i,list(islice(it, i))) for i in range(1, len(l))))}
print(d)
{1: [1], 2: [2, 3], 3: [4, 5, 6], 4: [7, 8, 9, 10]}
需要花费更多时间:
In [18]: l = list(range(100000))
In [19]: %%timeit
it = iter(l)
d = {k: v for k,v in takewhile(itemgetter(1),((i,list(islice(it, i))) for i in range(1, len(l))))}
....:
100 loops, best of 3: 2.51 ms per loop
In [20]: %%timeit
it = iter(l)
d = {k: v for k,v in ((i,list(islice(it, i))) for i in range(1, len(l))) if v}
....:
10 loops, best of 3: 65.7 ms per loop
In [29]: timeit {k:v for k,v in enumerate(iter(lambda i=iter(group), c=count(1): list(islice(i, next(c))), []), 1)}
100 loops, best of 3: 2.74 ms per loop
In [33]: %%timeit
....: it = iter(l)
....: dict(zip(count(1), takewhile(lambda x: x, (list(islice(it, i)) for i in count(1)))))
....:
100 loops, best of 3: 2.73 ms per loop
好的数学胜利但不是我想的那么多:
In [23]: timeit dict(groups(l))
1000 loops, best of 3: 1.53 ms per loop
使用itertools.count
代替范围再敲一下:
n [36]: %%timeit
....: it = iter(l)
....: {k: v for k, v in takewhile(itemgetter(1),
....: ((i, list(islice(it, i))) for i in count(1)))}
....:
100 loops, best of 3: 2.38 ms per loop
有关更简洁的选项,请使用dict:
it = iter(l)
d= dict(takewhile(itemgetter(1),
((i, list(islice(it, i))) for i in count(1))))
答案 3 :(得分:2)
您的代码几乎正确,但逻辑已关闭。我添加了一个名为start
的变量,它是每个新组应该开始的索引,并将循环更改为while
;当start
大于或等于列表的长度时,我们已经处理了所有项目。
groups = {}
N = 1
group = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
start = 0
while start < len(group):
groups[N] = group[start:start + N]
start += N
N += 1
输出
{1: [1], 2: [2, 3], 3: [4, 5, 6], 4: [7, 8, 9, 10]}
此外,不需要使用更新,对字典键的简单分配在这里也可以。
答案 4 :(得分:2)
基于数学的解决方案:
import math
def groups(l):
for i in range(1,int((math.sqrt(8*len(l)+1)+1)/2)):
start = int(i*(i-1)/2)
yield i, l[start:start+i]
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
r = dict(groups(l))
结果:r == {1: [1], 2: [2, 3], 3: [4, 5, 6], 4: [7, 8, 9, 10]}
没有截断的版本:
import math
def groups(l):
for i in range(1,math.ceil((math.sqrt(8*len(l)+1)+1)/2)):
start = int(i*(i-1)/2)
yield i, l[start:min(start+i,len(l))]
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
r = dict(groups(l))
结果:r == {1: [1], 2: [2, 3], 3: [4, 5, 6], 4: [7, 8, 9, 10], 5: [11]}
答案 5 :(得分:1)
您可以使用生成器:
from itertools import count, repeat
def gen(it):
for i in count(1):
yield i, map(next, repeat(it, i))
print dict(gen(iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])))
结果:
{1: [1], 2: [2, 3], 3: [4, 5, 6], 4: [7, 8, 9, 10]}
或者只是:
from itertools import count, takewhile, islice, izip
it = iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
dict(izip(count(1), takewhile(lambda x: x, (list(islice(it, i)) for i in count(1)))))