以对数方式拆分Python列表

时间:2016-03-02 18:46:53

标签: python math split logarithm

我正在尝试做以下事情..

我有一个n个元素的列表。我希望将此列表拆分为32个单独的列表,这些列表包含越来越多的元素,因为我们将朝向原始列表的末尾。例如来自:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

我想得到这样的东西:

b = [[1],[2,3],[4,5,6,7],[8,9,10,11,12]]

我已经为包含1024个元素的列表完成了以下操作:

for i in range (0, 32):
    c = a[i**2:(i+1)**2]
    b.append(c)

但我愚蠢地努力寻找一种可靠的方法来为其他数字(如256,512,2048或其他数量的列表而不是32位)执行此操作。

4 个答案:

答案 0 :(得分:1)

这样的事情可以解决问题。

for i in range (0, int(np.sqrt(2*len(a)))):
    c = a[i**2:min( (i+1)**2, len(a) )]
    b.append(c)

不是非常pythonic但是做你想要的。

def splitList(a, n, inc):
    """
    a list to split
    n number of sublist
    inc ideal difference between the number of elements in two successive sublists
    """
    zr = len(a) # remaining number of elements to split into sublists
    st = 0 # starting index in the full list of the next sublist
    nr = n # remaining number of sublist to construct
    nc = 1 # number of elements in the next sublist
    #
    b=[]
    while (zr/nr >= nc and nr>1):
        b.append( a[st:st+nc] )
        st, zr, nr, nc = st+nc, zr-nc, nr-1, nc+inc
    #
    nc = int(zr/nr)
    for i in range(nr-1):
        b.append( a[st:st+nc] )
        st = st+nc
    #
    b.append( a[st:max(st+nc,len(a))] )
    return b

# Example of call
# b = splitList(a, 32, 2)
# to split a into 32 sublist, where each list ideally has 2 more element
# than the previous

答案 1 :(得分:1)

总是这样。

>>> def log_list(l):
    if len(l) == 0:
        return [] #If the list is empty, return an empty list

    new_l = [] #Initialise new list
    new_l.append([l[0]]) #Add first iteration to new list inside of an array

    for i in l[1:]: #For each other iteration,
        if len(new_l) == len(new_l[-1]):
            new_l.append([i]) #Create new array if previous is full
        else:
            new_l[-1].append(i) #If previous not full, add to it

    return new_l

>>> log_list([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]

答案 2 :(得分:1)

使用iteratorfor循环enumerateitertools.islice

import itertools
def logsplit(lst):
    iterator = iter(lst)
    for n, e in enumerate(iterator):
        yield itertools.chain([e], itertools.islice(iterator, n))

适用于任意数量的元素。例如:

for r in logsplit(range(50)):
    print(list(r))

输出:

[0]
[1, 2]
[3, 4, 5]
[6, 7, 8, 9]
... some more ...
[36, 37, 38, 39, 40, 41, 42, 43, 44]
[45, 46, 47, 48, 49]

事实上,这与this problem非常相似,只是它使用enumerate来获取可变的块大小。

答案 3 :(得分:1)

这非常混乱,但完成工作。请注意,如果您以对数方式对列表进行切片,那么您最初会获得一些空箱。您的示例给出了算术索引序列。

from math import log, exp

def split_list(_list, divs):
    n = float(len(_list))
    log_n = log(n)
    indices = [0] + [int(exp(log_n*i/divs)) for i in range(divs)]
    unfiltered = [_list[indices[i]:indices[i+1]] for i in range(divs)] + [_list[indices[i+1]:]]
    filtered = [sublist for sublist in unfiltered if sublist]
    return [[] for _ in range(divs- len(filtered))] + filtered


print split_list(range(1024), 32)

修改:查看评论后,这里有一个可能符合您需求的示例:

def split_list(_list):
    copy, output = _list[:], []
    length = 1
    while copy:
        output.append([])
        for _ in range(length):
            if len(copy) > 0:
                output[-1].append(copy.pop(0))
        length *= 2
    return output


print split_list(range(15))
# [[0], [1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14]]

请注意,此代码效率不高,但可以用作编写更好算法的模板。