python - 算法 : how to split list data into fixed size sub-lists without having separate numbers

标签 python python-3.x list algorithm sublist

我有一道算法题要问你。不需要应用程序上下文,我会给你一个直接的例子。

这是一个可能的输入:input = [ 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 4 ]。 假设批量大小为 5。 这里的想法是输出最大大小为 5 的列表,而没有单独的数字,简而言之:2 个相同的数字不能在单独的子列表中。 示例输出:[ [1, 1, 1], [2, 2, 2, 2], [3, 3, 4, 4, 4] ]

假设:数字总是排序的,batch_size 总是大于可能的数字数量

你有比我刚刚找到的更优雅的解决方案吗?

i = 0
batch_size = 5
res = []
while i < len(input):
    # Retrieve the data list according to the batch size
    data = input[i: i + size]
    # Increment the index
    i += size
    # See what's the next output looks like
    future_data = input[i: i + size]
    if future_data and future_data[0] == data[-1]:
        # So we count how many times this number appears in our current list 
        # and subtract that from our index
        cp = data.count(data[-1])
        i -= cp
        # Then remove from the current list all occurrence of that number
        data = data[:-cp]
    res.append(data)

编辑:根据@juanpa.arrivillaga 的回答:

感谢大家的 react 和回答。

我继续第 2 集,我在这里给了你我的简化问题,我认为你的解决方案就足够了,尽管你的回应,我不知道如何使 @juanpa.arrivillaga 的解决方案适应我的数据格式,事实上输入看起来更像是:

input = { 
    'data_1' : { 
        'id': [1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 4], 
        'char': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'] 
    }
}

!'id' 和 'char' 值列表的大小必须相等!

输出必须如下所示:

[ 
    [1, 'A', 1, 'B', 1, 'C'], 
    [2, 'D', 2, 'E', 2, 'F', 2, 'G'], 
    [3, 'H', 3, 'I', 4, 'J', 4, 'K', 4, 'L'] 
]

我知道数据结构不是最优的,不幸的是我没有手,因此无法更改...

还是和之前一样的约束(batch size 只作用于 id,我够清楚了吧?)

最佳答案

以下是我将如何一次性完成此操作:

>>> import itertools
>>> batch_size = 5
>>> result = [[]]
>>> input_data = [ 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4 ]
>>> for _, g in itertools.groupby(input_data):
...     current = list(g)
...     if len(result[-1]) + len(current) <= batch_size:
...         result[-1].extend(current)
...     else:
...         result.append(current)
...
>>> result
[[1, 1, 1], [2, 2, 2, 3, 3], [4, 4, 4]]

让我们将其分解为中间步骤以帮助理解,首先,这是 itertools.groupby 热切评估的内容:

>>> import itertools
>>> batch_size = 5
>>> grouped = [list(g) for k,g in itertools.groupby([ 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4 ])]
>>> grouped
[[1, 1, 1], [2, 2, 2], [3, 3], [4, 4, 4]]

然后,简单地建立你的结果,这是一个子列表列表。如果它可以放入当前子列表,则将该组添加到子列表,否则,附加一个由该组组成的新子列表(我们可以假设它不大于​​ batch_size):

>>> result = [[]]
>>> for group in grouped:
...     if len(result[-1]) + len(group) <= batch_size:
...         result[-1].extend(group)
...     else:
...         result.append(group[:])
...
>>> result
[[1, 1, 1], [2, 2, 2, 3, 3], [4, 4, 4]]

上面对数据进行了两次传递,发布的第一个示例进行了一次传递。

请注意,如果使用 itertools.groupby 感觉像是在“作弊”,您可以实现一些相对容易的方法来解决这种情况:

def simple_groupby(data):
    it = iter(data)
    empty = object()
    current = next(it, empty)
    if current is empty:
        return
    prev = current
    acc = [current]
    for current in it:
        if prev == current:
            acc.append(current)
        else:
            yield acc
            acc = [current]
        prev = current
    yield acc

关于python - 算法 : how to split list data into fixed size sub-lists without having separate numbers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67615600/

相关文章:

python - Tkinter,当调整大小为 False 时启用最大化按钮

python - 创建 "Flashcard"词汇程序

python - 是否可以从字符串数据列表创建字典列表?

python - 使用 Python 将字符串解析为重叠对

python - 在 tf.keras 中使用 tensorflow eager execution 时出现警告 `tried to deallocate nullptr`

python - 值错误 : could not convert string to float : bored

python - 下载文件的上次修改时间与其 HTTP header 不匹配

python - 通过 CTRL+C 中断所有线程

Python dataframes - 如何在此处应用线程/多重处理来加快速度

python - 将行列表拆分为二维数组