如何找到最小长度为 3 的所有可能的连续且不重叠的子列表

How to find all possible consecutive and not overlapping sublists with minimum length of 3

我真正想做的是在一些数据中拟合所有可能的直线,并通过测量它们的平均 R 平方找到最佳拟合线组。

我卡住的步骤是如何使用足够的方法获得所有这些可能的子列表,以便我可以在之后进行调整。这也是为什么我想要最小长度为 3 的原因,因为通过两点的每条线都完美契合,我不希望那样。

例如,我的第一次尝试是这样的:

def sub_lists(lst):
    lr = [lst[:i] for i in range(3,len(lst)-2)]
    rl = [lst[i:] for i in range(len(lst)-3,2,-1)]
    return [[lr[i], rl[-i-1]] for i in range(len(lr))]

>>> tst = [489, 495, 501, 506, 508, 514, 520, 522]
>>> sub_lists(tst)
[[[489, 495, 501], [506, 508, 514, 520, 522]],
[[489, 495, 501, 506], [508, 514, 520, 522]],
[[489, 495, 501, 506, 508], [514, 520, 522]]]

但后来我遇到了下面的长度为 5 的列表,但它没有 work.Thus 预期的输出只是列表:

>>> tst = [489, 495, 501, 506, 508]
>>> sub_lists_revised(tst)
[489, 495, 501, 506, 508]

当我有更大长度的数据时遵循相同的逻辑,例如 10:

>>> tst = [489, 495, 501, 506, 508, 514, 520, 525, 527, 529]
>>> sub_lists_revised(tst)
# the whole list
[489, 495, 501, 506, 508, 514, 520, 525, 527, 529]
# all possible pairs
[[[489, 495, 501], [506, 508, 514, 520, 525, 527, 529]],
[[489, 495, 501, 506], [508, 514, 520, 525, 527, 529]],
[[489, 495, 501, 506, 508], [514, 520, 525, 527, 529]],
[[489, 495, 501, 506, 508, 514], [520, 525, 527, 529]],
[[489, 495, 501, 506, 508, 514, 520], [525, 527, 529]]]
# and finally, all possible triplets which i couldn't figure out
[[[489, 495, 501], [506, 508, 514], [520, 525, 527, 529]],
[[489, 495, 501], [506, 508, 514, 520], [525, 527, 529]],
[[489, 495, 501, 506], [508, 514, 520], [525, 527, 529]]]

总而言之,我想要的是一种适用于更多数据的通用方法,尽管我认为目前我真的不需要三胞胎。

我还在拟合后添加了第一个示例中的数字:fig1, fig2, fig3

这里有一个递归的方法。

第一个函数为长度为 n 的列表生成可能的切割点,至少生成长度为 3 的子列表。

第二个只是产生子列表,根据切割点切割

两者都是生成器,因此如果您在循环中使用它们,则子列表会即时生成,一次生成一个。这可能很有用,因为当您的数据变长时,可能的子列表数量可能会增长得非常高。

def cut_points(n, already_cut=None):
    # The first cut point is at 0 
    if already_cut is None:
        already_cut = [0]

    # We can cut at all places between the last cut plus 3 
    # and the length minus 3, and yield recursively the solutions for each choice
    for i in range(already_cut[-1]+3, n-2):
        cuts = already_cut[:] + [i]
        yield from cut_points(n, cuts)

    # When we tried all cut points and reached the total length, we yield the cut points list 
    yield already_cut[:] + [n]


def all_possible_sublists(data):
    n = len(data)
    for cut in cut_points(n):
        yield [data[cut[i]:cut[i+1]] for i in range(len(cut)-1)]

一些测试:

list(all_possible_sublists([0, 1, 2, 3]))
# [[[0, 1, 2, 3]]]

list(all_possible_sublists([0, 1, 2, 3, 4, 5, 6]))
# [[[0, 1, 2], [3, 4, 5, 6]],
#  [[0, 1, 2, 3], [4, 5, 6]],
#  [[0, 1, 2, 3, 4, 5, 6]]]

for sublist in all_possible_sublists([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]):
    print(sublist)
# [[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
# [[0, 1, 2], [3, 4, 5, 6], [7, 8, 9]]
# [[0, 1, 2], [3, 4, 5, 6, 7, 8, 9]]
# [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]
# [[0, 1, 2, 3], [4, 5, 6, 7, 8, 9]]
# [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
# [[0, 1, 2, 3, 4, 5], [6, 7, 8, 9]]
# [[0, 1, 2, 3, 4, 5, 6], [7, 8, 9]]
# [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]