将 UnitLength 的 Measurement() 数组转换为相同的自然比例
Convert array of Measurement() of UnitLength to same natural scale
我有一组 UnitLength 值(攀登高度),我想在图表中显示这些值。
原始数据以米为单位存储,因此我需要将这些值转换为用户的本地化单位(例如英尺)。
Apple 对此有很好的 API:
let measurementFormatter = MeasurementFormatter()
measurementFormatter.unitOptions = .naturalScale
let measurement = Measurement(value: valueInMeters, unit: UnitLength.meters)
measurementFormatter.string(from: measurement)
所以现在,我将一个数据点转换为自然比例。但是,我现在需要将整个 dayapoints 数组转换为相同的单位。但我不知道 measurementFormatter 使用的是哪个单位。结果单位是什么?
否则,如果我单独转换所有值,有些值会非常小,因此 naturalScale 将为英寸。
最后,我希望 naturalScale 取决于平均值或中值,以便大多数值都在其自然范围内。
我不明白这怎么可能 API – 除了做一些像这样的愚蠢的事情:
let symbol = measurementFormatter.string(from: measurement).split(separator: " ").last?.lowercased()
// is there not better way to get the UnitLength from naturalScale conversion result?
if symbol == "m" {
return .meters
}
if symbol == "ft" {
return .feet
}
if symbol == "yd" {
return .yards
}
if symbol == "in" {
return .inches
}
if symbol == "cm" {
return .centimeters
}
if symbol == "mm" {
return .millimeters
}
if symbol == "km" {
return .kilometers
}
if symbol == "mi" {
return .miles
}
但我不想发送此代码。没有更好的选择吗?
让我们从这个数组开始:
let dataPoints = [0.0001, 0.1, 1, 2, 3, 1000, 2000]
最适合此数组的单位是中值单位:
let median = dataPoints.sorted(by: <)[dataPoints.count / 2]
let medianMeasurement = Measurement(value: 1700, unit: UnitLength.meters)
在下面的代码片段中我们找出了最合适的单位,如果单位刚好小于数据点那么它被认为是自然单位:
let imperialUnitsNames: [UnitLength] = [.inches,
.feet,
.yards,
.fathoms,
.furlongs,
.miles,
]
let imperialUnitsInMeters: [Any] = imperialUnitsNames.map { unit in
let m = Measurement(value: 1, unit: unit).converted(to: .meters)
return m.value
}
let zipped = zip(imperialUnitsInMeters, imperialUnitsNames)
let naturalUnit = zipped.reversed()
.first(where: { [=12=].0 < median})!
.1
您可以在 imperialUnitsNames
中自定义可能的单位。
让我们创建一个测量格式器:
let measurementFormatter = MeasurementFormatter()
measurementFormatter.unitOptions = .providedUnit
现在我们准备格式化 dataPoints
:
let measurementStrings: [String] = dataPoints.map { dataPoint in
let measurement = Measurement(value: dataPoint, unit: UnitLength.meters)
let newMeasurement = measurement.converted(to: naturalUnit)
return measurementFormatter.string(from: newMeasurement)
}
print(measurementStrings) //["0 ftm", "0.055 ftm", "0.547 ftm", "1.094 ftm", "1.64 ftm", "546.807 ftm", "1,093.613 ftm"]
我有一组 UnitLength 值(攀登高度),我想在图表中显示这些值。 原始数据以米为单位存储,因此我需要将这些值转换为用户的本地化单位(例如英尺)。 Apple 对此有很好的 API:
let measurementFormatter = MeasurementFormatter()
measurementFormatter.unitOptions = .naturalScale
let measurement = Measurement(value: valueInMeters, unit: UnitLength.meters)
measurementFormatter.string(from: measurement)
所以现在,我将一个数据点转换为自然比例。但是,我现在需要将整个 dayapoints 数组转换为相同的单位。但我不知道 measurementFormatter 使用的是哪个单位。结果单位是什么?
否则,如果我单独转换所有值,有些值会非常小,因此 naturalScale 将为英寸。 最后,我希望 naturalScale 取决于平均值或中值,以便大多数值都在其自然范围内。
我不明白这怎么可能 API – 除了做一些像这样的愚蠢的事情:
let symbol = measurementFormatter.string(from: measurement).split(separator: " ").last?.lowercased()
// is there not better way to get the UnitLength from naturalScale conversion result?
if symbol == "m" {
return .meters
}
if symbol == "ft" {
return .feet
}
if symbol == "yd" {
return .yards
}
if symbol == "in" {
return .inches
}
if symbol == "cm" {
return .centimeters
}
if symbol == "mm" {
return .millimeters
}
if symbol == "km" {
return .kilometers
}
if symbol == "mi" {
return .miles
}
但我不想发送此代码。没有更好的选择吗?
让我们从这个数组开始:
let dataPoints = [0.0001, 0.1, 1, 2, 3, 1000, 2000]
最适合此数组的单位是中值单位:
let median = dataPoints.sorted(by: <)[dataPoints.count / 2]
let medianMeasurement = Measurement(value: 1700, unit: UnitLength.meters)
在下面的代码片段中我们找出了最合适的单位,如果单位刚好小于数据点那么它被认为是自然单位:
let imperialUnitsNames: [UnitLength] = [.inches,
.feet,
.yards,
.fathoms,
.furlongs,
.miles,
]
let imperialUnitsInMeters: [Any] = imperialUnitsNames.map { unit in
let m = Measurement(value: 1, unit: unit).converted(to: .meters)
return m.value
}
let zipped = zip(imperialUnitsInMeters, imperialUnitsNames)
let naturalUnit = zipped.reversed()
.first(where: { [=12=].0 < median})!
.1
您可以在 imperialUnitsNames
中自定义可能的单位。
让我们创建一个测量格式器:
let measurementFormatter = MeasurementFormatter()
measurementFormatter.unitOptions = .providedUnit
现在我们准备格式化 dataPoints
:
let measurementStrings: [String] = dataPoints.map { dataPoint in
let measurement = Measurement(value: dataPoint, unit: UnitLength.meters)
let newMeasurement = measurement.converted(to: naturalUnit)
return measurementFormatter.string(from: newMeasurement)
}
print(measurementStrings) //["0 ftm", "0.055 ftm", "0.547 ftm", "1.094 ftm", "1.64 ftm", "546.807 ftm", "1,093.613 ftm"]