Вот еще одно возможное решение:
let evenA = stride(from: 0, to: masterA.count, by: 2).map { masterA[$0] }
let oddA = stride(from: 1, to: masterA.count, by: 2).map { masterA[$0] }
Элементы «выбраны» непосредственно из четных / нечетных позиций в исходном массиве.
Сравнение производительности:
Мой простой, не очень сложный код для бенчмаркинга:
import Swift
let N = 10_000_000
let RUNS = 50
let masterA = (0..<N).map { $0 }
var times = (0.0, 0.0, 0.0, 0.0)
for _ in 1...RUNS {
// filter+map (dfri)
do {
let start = Date()
let evenA = masterA.enumerated().filter { $0.0 % 2 == 0 }.map{ $0.1 }
let oddA = masterA.enumerated().filter { $0.0 % 2 != 0 }.map{ $0.1 }
let time = Date().timeIntervalSince(start)
times.0 += time
}
// flatMap (dfri)
do {
let start = Date()
let evenA = masterA.enumerated().flatMap { $0 % 2 == 0 ? $1 : nil }
let oddA = masterA.enumerated().flatMap { $0 % 2 != 0 ? $1 : nil }
let time = Date().timeIntervalSince(start)
times.1 += time
}
// stride+map (me)
do {
let start = Date()
let evenA = stride(from: 0, to: masterA.count, by: 2).map { masterA[$0] }
let oddA = stride(from: 1, to: masterA.count, by: 2).map { masterA[$0] }
let time = Date().timeIntervalSince(start)
times.2 += time
}
// loop (Keiwan)
do {
let start = Date()
var evenA = [Int]()
var oddA = [Int]()
for (index, element) in masterA.enumerated() {
if index % 2 == 0 {
evenA.append(element)
} else {
oddA.append(element)
}
}
let time = Date().timeIntervalSince(start)
times.3 += time
}
}
print(N, RUNS)
print(times.0/Double(RUNS), times.1/Double(RUNS), times.2/Double(RUNS), times.3/Double(RUNS))
Результаты: (В MacBook, работающем в режиме деблокирования)
#elements filter+map flatMap stride+map loop 10,000 0.0001 0.00008 0.00004 0.00004 100,000 0.0016 0.0008 0.0004 0.0004 1,000,000 0.0295 0.0136 0.0090 0.0091 10,000,000 0.3025 0.1332 0.0909 0.1250
Учитывая, что в Rust (в отличие от C или C ++) адрес значения не считается существенным, в терминах language нет ничего, что предотвращало бы исключение копии.
Однако сегодня rustc ничего не оптимизирует: все оптимизации делегированы LLVM, и, похоже, вы столкнулись с ограничением оптимизатора LLVM здесь (неясно, связано ли это ограничение с LLVM, близким к семантике C или просто упущение).
Итак, есть два способа улучшения генерации кода для этого:
, но на данный момент вы можете просто захотеть избежать выделения таких больших объектов в стеке, вы можете Box
это например.