分配数组值,使最大值为1,最小值为0

5

我认为这应该是一个基本的数学运算,但我真的无法弄清楚。我需要根据给定数组中的值获取介于0和1之间的值数组。因此,例如,如果我们有一个初始数组[24, 128, 52],则结果数组应为[0, 1, 0.5]。最大值和最小值应始终为1和0,其余值应在它们之间成比例。

在Swift中,我该如何做到这一点?

3个回答

9

从一个数组开始:

let sourceArray = [24.0, 128.0, 52.0]

存储最小值和最大值元素:

let min = minElement(sourceArray) // 24.0
let max = maxElement(sourceArray) // 128.0

将每个元素进行标准化,并将结果映射到一个新的数组中:

let results = sourceArray.map { ($0 - min) / (max - min) }

results是:

[0, 1, 0.2692307692307692]

你提供了[0, 1, 0.5],但我认为这是错误的,因为你说“其余部分应该成比例分配”。输入[24.0, 128.0, 76.0]将输出[0, 1, 0.5]
注意:如果源数组是[Int],则map操作将会将结果四舍五入为1或0。如果您需要使用[Int]进行操作,您需要在map操作中转换每个元素。

非常感谢。这里提醒一下后面的读者,如果你正在使用Swift 2.0,你需要使用sourceArray.minElement()代替minElement(sourceArray)。 - rmvz3

3
在Swift 5中使用:
let min = sourceArray.min()
let max = sourceArray.max()
// will produce optionals! Unwrap them if you are sure they won't be nil
let results = sourceArray.map { ($0 - min!) / (max! - min!) }

如果最小值和最大值相同,这将会崩溃。 - Cristik

0
let array: [Double] = [24, 128, 52]
array.map { [range = ClosedRange(encompassing: array)!] in
  range.normalize($0)!
}

public extension ClosedRange {
  /// A range whose bounds are the extremes of a given sequence.
  ///
  /// - Returns: `nil` if the sequence is empty.
  init?<Bounds: Sequence>(encompassing bounds: Bounds)
  where Bounds.Element == Bound {
    guard let initialRange = ( bounds.first.map { $0...$0 } )
    else { return nil }

    self = bounds.dropFirst().reduce(into: initialRange) { range, bound in
      if bound < range.lowerBound {
        range = bound...range.upperBound
      } else if bound > range.upperBound {
        range = range.lowerBound...bound
      }
    }
  }
}

public extension ClosedRange where Bound: AdditiveArithmetic {
  /// `upperBound - lowerBound`
  var magnitude: Bound { upperBound - lowerBound }
}

public extension ClosedRange where Bound: FloatingPoint {
  /// A value whose unit is the `magnitude` of this range,
  /// and whose origin is `lowerBound`.
  ///
  /// - Note: Not clamped between 0 and 1.
  ///
  /// - Returns: `nil` when the range has zero magnitude.
  func normalize(_ bound: Bound) -> Bound? {
    try? (bound - lowerBound) ÷ magnitude
  }

infix operator ÷: MultiplicationPrecedence

public extension FloatingPoint {
  /// - Throws: `DivisionByZeroError<Self>`
  static func ÷ (numerator: Self, denominator: Self) throws -> Self {
    guard denominator != 0
    else { throw DivisionByZeroError(numerator: numerator) }

    return numerator / denominator
  }
}

public extension Sequence {
  /// The first element of the sequence.
  /// - Note: `nil` if the sequence is empty.
  var first: Element? {
    var iterator = makeIterator()
    return iterator.next()
  }
}

// Division isn't actually found in `Numeric`,
// but it does seem to be found in all the important protocols that inherit from it.
public struct DivisionByZeroError<Numerator: Swift.Numeric>: Error {
  public let numerator: Numerator

  public init(numerator: Numerator) {
    self.numerator = numerator
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接