我认为这应该是一个基本的数学运算,但我真的无法弄清楚。我需要根据给定数组中的值获取介于0和1之间的值数组。因此,例如,如果我们有一个初始数组[24, 128, 52]
,则结果数组应为[0, 1, 0.5]
。最大值和最小值应始终为1和0,其余值应在它们之间成比例。
在Swift中,我该如何做到这一点?
从一个数组开始:
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
操作中转换每个元素。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!) }
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
}
}