我上了这个课:
class ValueTimestamp {
let value: Double
let timestamp : Double
init(value:Double, timestamp:Double) {
self.value = value
self.timestamp = timestamp
}
}
然后我有一个此类的对象数组。
现在,我想扫描该数组并找到具有最小值的ValueTimestamp
类的对象。
假设数组有3个元素
element1
(值= 12,时间戳= 2)element2
(值= 5,时间戳= 3)element3
(值= 10,时间戳= 4)和
let myArray = [element1, element2, element3]
现在我想找到具有最小值的元素。
我认为这会起作用
let min = myArray.map({$0.value}).min()
let minIndex = myArray.firstIndex(of: min)
但是第二行给了我这个错误
调用中的参数标签不正确(具有“ of:”,预期为“ where:”)
有什么想法吗?
答案 0 :(得分:4)
firstIndex:of:
查找等于提供的参数的第一个元素。但是,您并不是在寻找与之相等的元素,而是在寻找其value
属性相等的元素。因此,您需要使用where
并为此提供一个函数:
let minIndex = myArray.firstIndex(where: {$0.value == min})
您还可以使您的班级符合Comparable
并直接在其上调用min
:
class ValueTimestamp: Comparable {
let value: Double
let timestamp : Double
init(value:Double, timestamp:Double) {
self.value = value
self.timestamp = timestamp
}
static func == (lhs: ValueTimestamp, rhs: ValueTimestamp) -> Bool {
return lhs.value == rhs.value
}
static func < (lhs: ValueTimestamp, rhs: ValueTimestamp) -> Bool {
return lhs.value < rhs.value
}
}
let minObject = myArray.min()
请注意,如果可能有两个对象具有相同的value
,则可能需要调整功能以确定在那种情况下哪个对象“少”。
答案 1 :(得分:2)
firstIndex(of: )
不起作用,因为我认为您的课程不符合Equatable
。
这就是为什么您希望在这种情况下使用firstIndex(where:)
的原因。
同样在下面的代码中您没有得到对象,而是得到了值,所以min
是Double?
而不是ValueTimeStamp?
的类型:
let min = myArray.map({$0.value}).min()
您可以使用where获得以下内容的最小值索引:
let minIndex = myArray.firstIndex(where: {$0.value == min})
参考文献:
https://developer.apple.com/documentation/swift/array/2994720-firstindex https://developer.apple.com/documentation/swift/array/2994722-firstindex
答案 2 :(得分:0)
这里的根本原因是firstIndex(of:_)
仅在Collection where Element: Equatable
上定义。您的类型不可更改,因此只有在您使其符合标准之前,您才可以使用此方法。
但是,使用Array.enumerated()
和Array.min(by:_)
可以更优雅地解决您的问题:
如果仅需要元素,则可以执行以下操作:
let timestampedValues = [element1, element2, element3]
let minTimestampedValue = timestampedValues
.enumerated()
.min(by: { $0.value })
print(minTimestampedValue as Any)
如果只需要索引,则可以执行以下操作:
let minTimestampedValueIndex = timestampedValues
.enumerated()
.min(by: { $0.element.value < $1.element.value })?.offset
print(minTimestampedValueIndex as Any)
如果两者都想要,您可以这样做:
let minTimestampedValuePair = timestampedValues
.enumerated()
.min(by: { $0.element.value < $1.element.value })
print(minTimestampedValuePair.offset as Any, minTimestampedValuePair.element as Any)
所有这三个摘要仅通过一次遍历数组即可获得答案,这使其比“查找最小值,然后找到其索引”方法快两倍。