我认为这必须是一个基本的数学运算,但我真的无法弄明白。我需要根据给定数组的值得到介于0和1之间的值数组。因此,例如,如果我们有一个初始数组[24, 128, 52]
,结果数组应为[0, 1, 0.5]
。最大值和最小值应始终分别为1和0,其余值应按比例在它们之间。
如何在Swift中执行此操作?
答案 0 :(得分:4)
从数组开始:
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]
,否则地图操作会将结果四舍五入为1或0.如果您需要使用[Int]
将必须转换map
操作中的每个元素。
答案 1 :(得分:1)
在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!) }
答案 2 :(得分: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
}
}