切片列表和组

时间:2015-04-30 19:48:00

标签: python list

例如,如果我们的源列表是:

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

6 个答案:

答案 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)))))