使用列表对列表进行分区

Partitioning a List using a List

我正在做一个项目,该项目要求我使用列表对列表进行分区。我创建了一个在某些情况下有效但并非在所有情况下都有效的解决方案。有谁能帮我解决逻辑问题吗?

有两个列表。每个列表的总和将始终相等。第一个列表(即partitionBy列表)用于对第二个列表(即inputList)进行分区。

这是一个简化的例子:

列表 A {3, 2, 4} 列表 B {2, 1, 1, 1, 3, 1}

列表A的第一项是3。列表B的第一项和第二项之和= 3(即2 + 1)。为这些项目创建一个列表

列表A的第二项是2。列表B的第三项和第四项之和=2(即1+1)。为这些项目创建一个列表

等...

理想的结果是:{{2, 1}, {1, 1}, {3, 1}}

代码目前在 AppleScript 中,但如果有帮助,我很乐意将其翻译成 JavaScript。

这是带示例的代码:

--Example 1 works as expected
set partitionBy1 to {4, 1, 9, 6, 2, 2} -- list to partition by
set inputList1 to   {1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 1} -- list to partition

-- required output: {{1, 1, 1, 1}, {1}, {2, 2, 2, 3}, {3, 3}, {1, 1}, {1, 1}}
-- actual output:   {{1, 1, 1, 1}, {1}, {2, 2, 2, 3}, {3, 3}, {1, 1}, {1, 1}}

--Example 2 works as expected
set partitionBy2 to {4, 2, 8, 6, 2, 2}
set inputList2 to   {1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 1}

-- required output: {{1, 1, 1, 1}, {1, 1}, {1, 2, 2, 3}, {3, 3}, {1, 1}, {1, 1}}
-- actual output:   {{1, 1, 1, 1}, {1, 1}, {1, 2, 2, 3}, {3, 3}, {1, 1}, {1, 1}}

--Example 3 does not work as expected
set partitionBy3 to {4, 1, 9, 1, 3, 6, 2, 2}
set inputList3 to   {1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 3, 3, 1, 1, 1, 1}

-- required output: {{1, 1, 1, 1}, {1}, {2, 2, 2, 3}, {1}, {3}, {3, 3}, {1, 1}, {1, 1}}
-- actual output:   {{1, 1, 1, 1}, {1}, {2, 2, 2, 3}, {3}, {3}, {3, 3}, {1, 1}, {1, 1}}


partitionList(inputList3, partitionBy3)

on partitionList(inputList, partitionBy)
    set partitionedList to {}
    repeat with i from 1 to (count partitionBy)
        set partitionNumber to item i of partitionBy
        set runningTotal to 0
        set intermediateList to {}
        repeat with j from 1 to ((count inputList) - 1)
            set inputNumber to item j of inputList
            set runningTotal to runningTotal + inputNumber
            if runningTotal = partitionNumber then
                set end of partitionedList to (intermediateList & inputNumber)
                set inputList to items (j + 1) thru -1 of inputList
                exit repeat
            else if runningTotal > partitionNumber then
                set item j of inputList to (inputNumber - 1)
                set inputList to (inputNumber - 1) & inputList
                set end of partitionedList to (intermediateList & (inputNumber - 1))
                set inputList to items (j + 1) thru -1 of inputList
                exit repeat
            else
                set end of intermediateList to inputNumber
            end if
        end repeat
    end repeat
    set end of partitionedList to intermediateList & item -1 of inputList
    return partitionedList
end partitionList

问题是j的线性递增。

runningTotal > partitionNumber 的情况下,您必须将差异(或余数)分配给 inputNumber 并在不递增 j.

的情况下评估下一个分区

我将 repeat with 替换为 repeat while,添加了一个 overflow 变量以指示 runningTotal 大于 partitionNumber 并声明了 j作为具有完全控制权的局部变量。

on partitionList(inputList, partitionBy)
    set partitionedList to {}
    set j to 1
    set overflow to false
    repeat with i from 1 to (count partitionBy)
        set partitionNumber to item i of partitionBy
        set runningTotal to 0
        set intermediateList to {}
        repeat while j < (count inputList)
            if overflow then
                set overflow to false
            else
                set inputNumber to item j of inputList
            end if
            set runningTotal to runningTotal + inputNumber
            if runningTotal = partitionNumber then
                set end of partitionedList to (intermediateList & inputNumber)
                set j to j + 1
                exit repeat
            else if runningTotal > partitionNumber then
                set end of partitionedList to {partitionNumber}
                set overflow to true
                set inputNumber to runningTotal - partitionNumber
                exit repeat
            else
                set end of intermediateList to inputNumber
                set j to j + 1
            end if
        end repeat
    end repeat
    set end of partitionedList to intermediateList & item -1 of inputList
    return partitionedList
end partitionList