first index:of:在一系列对象中



我有这个类:

class ValueTimestamp {
  let value: Double
  let timestamp : Double
  init(value:Double, timestamp:Double) {
    self.value = value
    self.timestamp = timestamp
  }
}

然后我有一个类别的对象。

现在我想扫描该数组,并找到具有最小值的ValueTimestamp类的对象。

假设数组有3个元素

  1. element1(值= 12,时间戳= 2)
  2. element2(值= 5,时间戳= 3)
  3. element3(值= 10,时间戳= 4)

let myArray = [element1, element2, element3]

现在我想找到具有最小值的元素。

我认为这会起作用

let min = myArray.map({$0.value}).min()
let minIndex = myArray.firstIndex(of: min)

但是第二行给我这个错误

呼叫中的不正确参数标签(具有:',预期'where:')

有什么想法?

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的对象,则可能需要调整功能以确定哪个对象在这种情况下是"少"。

firstIndex(of: )不起作用,因为我认为您的班级不符合Equatable

这就是为什么您期望使用firstIndex(where:)的原因。

在下面的代码中,您没有得到对象,您正在获得该值,因此minDouble?的类型,而不是ValueTimeStamp?

let min = myArray.map({$0.value}).min()

您可以使用以下方式获得最小索引,并使用以下位置:

let minIndex = myArray.firstIndex(where: {$0.value == min})

参考:

https://developer.apple.com/documentation/swift/array/2994720-firstindexhttps://developer.apple.com/documentation/swift/array/2994722-firstindex

根本原因是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)

所有这三个片段都只使用单个通过数组获得答案,这使得它们的速度是"查找最小的,然后找到其索引"的两倍。