我正在寻找一种方法来将数组拆分成具有最大值的块,但似乎找不到解决方案.

假设我们有以下代码:

struct FooBar {
    let value: Int
}

let array: [FooBar] = [
    FooBar(value: 1),
    FooBar(value: 2),
    FooBar(value: 1),
    FooBar(value: 1),
    FooBar(value: 1),
    FooBar(value: 2),
    FooBar(value: 2),
    FooBar(value: 1)
]

我们希望将其拆分成FooBar.Value的MaxSize不超过3的块.最终结果应该类似于:

let ExpectedEndResult: [[FooBar]] = [
    [
        FooBar(value: 1),
        FooBar(value: 2)
    ],
    [
        FooBar(value: 1),
        FooBar(value: 1),
        FooBar(value: 1)
    ],
    [
        FooBar(value: 2),
    ],
    [
        FooBar(value: 2),
        FooBar(value: 1)
    ]
]

我已经写了到目前为止,但有一个问题,当第三个项目可以添加,也…我相信一定有更简单的方法,但我现在想不出一个:

extension Array where Element == FooBar {

    func chunked(maxValue: Int) -> [[FooBar]] {
        var chunks: [[FooBar]] = []
        var chunk: [FooBar] = []

        self.enumerated().forEach { key, value in
            chunk.append(value)
            if self.count-1 > key {
                let next = self[key+1]

                if next.value + value.value > maxValue {
                    chunks.append(chunk)
                    chunk = []
                }
            } else {
                chunks.append(chunk)
            }
        }

        return chunks
    }
}

有什么建议吗?

推荐答案

我会用reduce(into:)英镑买这个

let maxValue = 3 //limit
var currentValue = 0 // current total value for the last sub array
var index = 0 // index of last (current) sub array
let groups = array.reduce(into: [[]]) {
    if $1.value > maxValue || $1.value + currentValue > maxValue {
        $0.append([$1])
        currentValue = $1.value
        index += 1
    } else {
        $0[index].append($1)
        currentValue += $1.value
    }
}

为了使它更通用,下面是一个泛型函数,作为数组的扩展,它也使用KeyPath作为值来分块

extension Array {
    func chunk<ElementValue: Numeric & Comparable>(withLimit limit: ElementValue, 
                                                   using keyPath: KeyPath<Element, ElementValue>) -> [[Element]] {
        var currentValue = ElementValue.zero
        var index = 0

        return self.reduce(into: [[]]) {
            let value = $1[keyPath: keyPath]
            if value > limit || value + currentValue > limit {
                $0.append([$1])
                currentValue = value
                index += 1
            } else {
                $0[index].append($1)
                currentValue += value
            }
        }
    }
}

样品的用法

let result = array.chunk(withLimit: 3, using: \.value)

Swift相关问答推荐

如何在一个角色隔离类上编写自定义==实现?

如何将泛型函数存储到变量中?

.onReceive NSWindow.CloseNotify是否会为App中的每个窗口调用?

如何防止自动状态恢复,如果应用程序被启动打开特定的文档?

如何在visionOS中进行购买?&# 39;购买(选项:)在visionOS中不可用

SwiftUI轨迹绘制怪异

无法创建MKAssociateRegion对象

在NavigationStack上设置拐角半径:SwiftUI中的无响应内容视图区

在Swift中,将秒设置为0也等于将1添加到分钟

在 SwiftUI 视图中观察 UIViewRepresentable 的 @State var 变化

如何使用模型在 SwiftUI 的列表中进行搜索

在表单中对齐文本框

(Swift)混淆了函数内 for-in 循环的返回值和循环后(函数内)的返回值)

当变量首次用于其自己的初始化时,如何清除变量...在初始化之前使用错误?

需要将 json 映射到 Swift 中的模型

如何删除 macOS 中的所有命令?

从 Int 到 String 的属性更改引发 SwiftUI 视图不更新

如何在 Swift 中使用子定义覆盖父类扩展

Swift:withCheckedContinuation 和 Dispatch QoSClass

在 Swift 中,你可以用另一个字符串分割一个字符串,而不仅仅是一个字符吗?