以对数方式拆分 Python 列表

Split a Python list logarithmically

我正在尝试执行以下操作..

我有一个包含 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 执行此操作。

像这样应该可以解决问题。

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

总是这样。

>>> 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]]

使用 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 来获取可变块大小。

这非常混乱,但可以完成工作。请注意,如果您对数 对列表进行切片,您将在开始时得到一些空箱。你的例子给出了算术索引序列。

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]]

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