通过抽取或提取 Swift 中的每个第 n 个元素进行下采样收集的有效方法
Efficient way of downsample collection via decimating or extracting every nth element in Swift
我正在尝试通过抽取或提取每个第 n 个元素来对长集合进行下采样。
这是我的数组扩展:
func downsampled(to threshold: Int) -> [T] {
// Validate that threshold falls in valid range
guard !isEmpty, 1...count ~= threshold else { return Array(self) }
let skip = (count / threshold) + 1
var index = 0
var items = [T]()
while index < count {
items.append(self[index])
index += skip
}
return items
}
我预计原始数组中有 50-100k 个项目,并且可能会下采样到屏幕的本机边界宽度(500-1k 点)。
是否有更简洁或更有效的方法?
extension RangeReplaceableCollection {
func every(from: Index? = nil, through: Index? = nil, nth: Int) -> Self { .init(stride(from: from, through: through, by: nth)) }
}
extension Collection {
func stride(from: Index? = nil, through: Index? = nil, by: Int) -> AnySequence<Element> {
var index = from ?? startIndex
let endIndex = through ?? self.endIndex
return AnySequence(AnyIterator {
guard index < endIndex else { return nil }
defer { index = self.index(index, offsetBy: by, limitedBy: endIndex) ?? endIndex }
return self[index]
})
}
}
游乐场测试
let array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
for element in array.stride(by: 3) {
print(element)
}
array.stride(by: 3).forEach {
print([=12=])
}
let nth = array.every(nth: 3) // [1, 4, 7, 10, 13]
let str = "0123456789"
for character in str.stride(by: 2) {
print(character)
}
str.stride(by: 2).forEach {
print([=12=])
}
let even = str.every(nth: 2) // "02468"
我正在尝试通过抽取或提取每个第 n 个元素来对长集合进行下采样。
这是我的数组扩展:
func downsampled(to threshold: Int) -> [T] {
// Validate that threshold falls in valid range
guard !isEmpty, 1...count ~= threshold else { return Array(self) }
let skip = (count / threshold) + 1
var index = 0
var items = [T]()
while index < count {
items.append(self[index])
index += skip
}
return items
}
我预计原始数组中有 50-100k 个项目,并且可能会下采样到屏幕的本机边界宽度(500-1k 点)。
是否有更简洁或更有效的方法?
extension RangeReplaceableCollection {
func every(from: Index? = nil, through: Index? = nil, nth: Int) -> Self { .init(stride(from: from, through: through, by: nth)) }
}
extension Collection {
func stride(from: Index? = nil, through: Index? = nil, by: Int) -> AnySequence<Element> {
var index = from ?? startIndex
let endIndex = through ?? self.endIndex
return AnySequence(AnyIterator {
guard index < endIndex else { return nil }
defer { index = self.index(index, offsetBy: by, limitedBy: endIndex) ?? endIndex }
return self[index]
})
}
}
游乐场测试
let array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
for element in array.stride(by: 3) {
print(element)
}
array.stride(by: 3).forEach {
print([=12=])
}
let nth = array.every(nth: 3) // [1, 4, 7, 10, 13]
let str = "0123456789"
for character in str.stride(by: 2) {
print(character)
}
str.stride(by: 2).forEach {
print([=12=])
}
let even = str.every(nth: 2) // "02468"