Arrays Swift数组最大值及其索引的高效算法
我已经编写了一个算法,用于在Swift数组中查找最大值及其索引。这是受到Matlab和Octave中的“max.m”函数的启发 这里的专家们能提出一种改进算法速度的方法吗?我的意思是,它是否可以变得更快,或者您认为这是一种适用于大型阵列(有时是15000个样本)的合理方法Arrays Swift数组最大值及其索引的高效算法,arrays,swift,max,Arrays,Swift,Max,我已经编写了一个算法,用于在Swift数组中查找最大值及其索引。这是受到Matlab和Octave中的“max.m”函数的启发 这里的专家们能提出一种改进算法速度的方法吗?我的意思是,它是否可以变得更快,或者您认为这是一种适用于大型阵列(有时是15000个样本)的合理方法 public func max(y:[Double])->(Int,Double){ 让inLen=y.count var out=Double() var outp=Int() if(1==inLen){//if只有一个元素
public func max(y:[Double])->(Int,Double){
让inLen=y.count
var out=Double()
var outp=Int()
if(1==inLen){//if只有一个元素
out=y[0]
输出=0
}else如果(0==inLen){//如果没有元素
out=-1
输出=-1
}否则{
out=y[0]
输出=0
对于1…inLen-1中的ii{
如果(输出代码)检查原始代码
这里是我将要做的更改。所有这些都有点粗糙(我没有检查是否所有这些都可以编译),但会让您走上正确的轨道
使代码通用
public func max (y: [Double]) -> (Int, Double) {
变成:
public func max<T: Comparable>(y: [T]) -> (Int, T) {
向结果中添加关键字:
public func max<T: Comparable>(_ array: [T]) -> (index: Int, value: T) {
内联不必要的变量inLen
,或者至少更好地命名它,就像count
将out
和outp
重命名为更好的名称,例如maxValue
和maxIndex
extension Array where Element: Comparable {
public func max() -> (index: Int, value: Element) {
if count == 0 { return (index: -1, value: -1) }
if count == 1 { return (index: 0, value: self[0]) }
var maxValue = self[0]
var maxIndex = 0
for i in 1...count-1 {
if (maxValue < self[i]) {
maxValue = self[i]
maxIndex = i
}
}
return (index: maxIndex, value: maxValue)
}
}
不要在Swift中使用yoda比较。=
不是Swift中的表达式,因此不会意外导致if语句中的赋值而不是比较。这会触发编译器错误。此外,请忽略
if (1 == count) {
应该是
if (count == 1) {
在if语句中省略不需要的并列关系:
if count == 1 {
以更合理的顺序重新排列计数检查。而不是1,0,1+,将其排序为0,1,1+
尽早返回,而不是使用if/elseif/else跳过代码块以获得公共返回。而不是:
extension Array where Element: Comparable {
public func max() -> (index: Int, value: Element) {
var maxValue = Double()
var maxIndex = Int()
if count == 0 { // if no elements
maxValue = -1
maxIndex = -1
} else if count == 1 { // if only one element
maxValue = self[0]
maxIndex = 0
} else {
maxValue = self[0]
maxIndex = 0
for i in 1...inLen-1 {
if (maxValue < self[i]){
maxValue = self[i]
maxIndex = i
}
}
}
return (index: maxIndex, value: maxValue)
}
}
避免重写诸如1…x-1等内容,而是使用。您可以使用
来自加速框架的函数。vDSP函数使用
(akaUInt
)用于数组计数和索引,因此必须转换
索引到Int
以实现快速互操作性
import Accelerate
let array: [Double] = ...
var elem = 0.0
var vdspIndex: vDSP_Length = 0
vDSP_maxviD(array, 1, &elem, &vdspIndex, vDSP_Length(array.count))
let idx = Int(vdspIndex)
print("max:", elem, "at index:", idx)
这比你的显式计算快了大约5倍
15000元素数组的循环(在发布模式下编译的iMac上).你在找代码审查吗?因为这段代码中有很多地方可以改进。嗨,Alexander——是的,我想是的!我应该在代码审查中发布它吗?在这里很好。我正在努力完成它,需要一段时间,有很多地方需要更改。好的,谢谢Alexander!我已经完成了我的第一次尝试。性能可能是一样的,但是质量大大提高了!如果您有任何问题,请告诉我Hanks Alexander&Martin!Martin,使用vDSP_maxviD函数,似乎我必须将idx转换为Int(idx)如果我想用它来获取另一个数组的元素,或者如果我需要向它添加一个整数。我在这里读到,特别是在循环中进行强制转换是不好的,因为它会消耗时间。如何克服idx的强制转换?@Pat:你只需将索引转换为Int一次。这与vDSP_maxviD调用相比可以忽略不计。@Pat我提供了一个包装器f或者我答案底部的代码。它使你在外部只处理好Swift类型/约定
extension Array where Element: Comparable {
public func max() -> (index: Int, value: Element) {
var maxValue = Double()
var maxIndex = Int()
if count == 0 { // if no elements
maxValue = -1
maxIndex = -1
} else if count == 1 { // if only one element
maxValue = self[0]
maxIndex = 0
} else {
maxValue = self[0]
maxIndex = 0
for i in 1...inLen-1 {
if (maxValue < self[i]){
maxValue = self[i]
maxIndex = i
}
}
}
return (index: maxIndex, value: maxValue)
}
}
extension Array where Element: Comparable {
public func max() -> (index: Int, value: Element)? {
var maxValue = Double()
var maxIndex = Int()
if count == 0 { return (index: -1, value: -1) }
if count == 1 { return (index: 0, value: self[0]) }
maxValue = self[0]
maxIndex = 0
for i in 1...count-1 {
if (maxValue < self[i]) {
maxValue = self[i]
maxIndex = i
}
}
return (index: maxIndex, value: maxValue)
}
}
extension Array where Element: Comparable {
public func max() -> (index: Int, value: Element) {
if count == 0 { return (index: -1, value: -1) }
if count == 1 { return (index: 0, value: self[0]) }
var maxValue = self[0]
var maxIndex = 0
for i in 1...count-1 {
if (maxValue < self[i]) {
maxValue = self[i]
maxIndex = i
}
}
return (index: maxIndex, value: maxValue)
}
}
for i in self.indicies {
for (index, value) in self.enumerated() {
extension Array where Element: Comparable {
public func max() -> (index: Int, value: Element)? {
if count == 0 { return nil }
if count == 1 { return (index: 0, value: self[0]) }
var maxValue = self[0]
var maxIndex = 0
for (index, value) in self.enumerated() {
if (maxValue < value) {
maxValue = value
maxIndex = index
}
}
return (index: maxIndex, value: maxValue)
}
}
extension Array where Element: Comparable {
public func max() -> (index: Int, value: Element)? {
if count == 0 { return nil }
if count == 1 { return (index: 0, value: self[0]) }
var (maxIndex, maxValue) = (0, self[0])
for (index, value) in self.enumerated() {
if (maxValue < value) {
(maxIndex, maxValue) = (index, value)
}
}
return (index: maxIndex, value: maxValue)
}
}
extension Array where Element: Comparable {
public func max() -> (index: Int, value: Element)? {
if count == 0 { return nil }
if count == 1 { return (index: 0, value: self[0]) }
var maxElement = (index: 0, value: self[0])
for (index, value) in self.enumerated() {
if (maxElement.value < value) { maxElement = (index, value) }
}
return maxElement
}
}
let array: [Double] = [3, 4, 5, 6, 7, 8, 9, 100, 100, 11, 12, 13, 14, 15, -8, -7, -7, 99]
if let (maxIndex, maxValue) = array.max() {
print("The max element is \(maxValue) at index \(maxIndex)")
}
else {
print("The array is empty, and has no max element or index.")
}
let array: [Double] = [3, 4, 5, 6, 7, 8, 9, 100, 100, 11, 12, 13, 14, 15, -8, -7, -7, 99]
if let (maxIndex, maxValue) = array.enumerated.max{ $0.element < $1.element } {
print("The max element is \(maxValue) at index \(maxIndex)")
}
else {
print("The array is empty, and has no max element or index.")
}
func max(of array: [Double]) -> (index: Int, value: Double)? {
var maxValue = Double()
var maxIndex = vDSP_Length()
vDSP_maxviD(array, 1, &maxValue, &maxIndex, vDSP_Length(array.count))
if maxValue == -Double.infinity { return nil }
return (index: Int(maxIndex), value: maxValue)
}
import Accelerate
let array: [Double] = ...
var elem = 0.0
var vdspIndex: vDSP_Length = 0
vDSP_maxviD(array, 1, &elem, &vdspIndex, vDSP_Length(array.count))
let idx = Int(vdspIndex)
print("max:", elem, "at index:", idx)