首页 > 解决方案 > 在Swift中合并值数组的最有效方法是什么

问题描述

我有一个稍微理论上的问题,但有一个非常实际的要求。

我试图找到基于多种因素合并 n 个大小相等的数组的最有效方法。这需要高性能。数组都是 512 字节,将以 40fps 进行评估。

规则(按顺序): 活动必须为真 最高优先级总是获胜 最大大小

结果数组是 512 x UInt8 值。

struct Slot {
   var size: UInt8
   var priority: UInt8
   var active: Bool
}

let source1 = [Slot(size: 0, priority: 100, active: true), Slot(size: 20, priority: 150, active: true), Slot(size: 150, priority: 100, active: true)]
let source2 = [Slot(size: 10, priority: 150, active: false), Slot(size: 40, priority: 100, active: true), Slot(size: 200, priority: 100, active: true)]
let source3 = [Slot(size: 20, priority: 200, active: false), Slot(size: 10, priority: 100, active: false), Slot(size: 30, priority: 100, active: true)]


// result expected [0, 20, 200]

我强调这完全与性能有关,生成的代码有多漂亮并不重要。

这是我正在寻找的 for in 循环:


struct Slot {
   var size: UInt8
   var priority: UInt8
   var active: Bool
}

let source1 = [Slot(size: 0, priority: 100, active: true), Slot(size: 20, priority: 150, active: true), Slot(size: 150, priority: 100, active: true)]
let source2 = [Slot(size: 10, priority: 150, active: false), Slot(size: 40, priority: 100, active: true), Slot(size: 200, priority: 100, active: true)]
let source3 = [Slot(size: 20, priority: 200, active: false), Slot(size: 10, priority: 100, active: false), Slot(size: 30, priority: 100, active: true)]

let sources = [source1, source2, source3]

var resultingArray = [UInt8]()

// loop through each array index
for index in 0...2 {

   let slots = sources.map { $0[index] }
   let activeSlots = slots.filter { $0.active }

   let sortedSlots = activeSlots.sorted {
      if $0.priority != $1.priority {
         return $0.priority > $1.priority
      } else {
        return $0.size > $1.size
      }
   }

    resultingArray.append(sortedSlots[0].size)

}

print(resultingArray)

标签: arraysswiftperformance

解决方案


因此,根据我对您评论的理解,您可以做的最好的事情是线性遍历每个数组以找到“获胜”插槽,然后提取大小。无需排序。

extension Slot: Comparable {
    static func < (lhs: Slot, rhs: Slot) -> Bool {
        !lhs.active && rhs.active ||
        lhs.active == rhs.active && (
            lhs.priority < rhs.priority ||
            lhs.priority == rhs.priority && lhs.size < rhs.size
        )
    }
}

let sizes = zip(source1, zip(source2, source3))
        .map { max(max($0, $1.0), $1.1).size }

其中,使用给定的值将产生:

[0, 20, 200]

推荐阅读