我有一组像[0.75, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0040000000000000001, ...]
这样的值,我需要删除重复项。我只想关注小数点后的前3位数。我该怎么做?
答案 0 :(得分:3)
您的问题强烈建议您使用错误的数据类型。我怀疑你真的只是想修改你的模型,而不是试图在unquing点修复它,所以问题不会发生。
如果要进行基于十进制的数学运算,则应使用基于十进制的数字,例如NSDecimalNumber
。例如,考虑到您确实有双打进入系统的情况,您可以通过这种方式将其转换为NSDecimalNumber
,具有“0.001准确度”:
let values = [0.75, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0040000000000000001]
let behavior = NSDecimalNumberHandler(roundingMode: .plain,
scale: 3,
raiseOnExactness: false,
raiseOnOverflow: false,
raiseOnUnderflow: false,
raiseOnDivideByZero: false)
let decimalNumbers = values.map {
NSDecimalNumber(value: $0).rounding(accordingToBehavior: behavior)
}
let uniqueDecimals = Set(decimalNumbers)
使用NSDecimalNumber
并应用适当的舍入规则后,大多数操作都会按预期工作。您可以将它们放入Set
以使它们独一无二。你可以检查是否平等。你可以打印它们,它们的行为就像十进制数字。让你的模型符合你的意思,大多数其他问题都会消失。
答案 1 :(得分:1)
您可以使用NumberFormatter来修复最小和最大小数位数,并使用一组来过滤重复元素:
let array = [0.75, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0040000000000000001]
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.minimumFractionDigits = 3
numberFormatter.maximumFractionDigits = 3
var set = Set<String>()
let orderedSet: [Double] = array.flatMap {
guard let string = numberFormatter.string(for: $0) else { return nil }
return set.insert(string).inserted ? $0 : nil
}
orderedSet // [0.75, 0.005, 0.004]
如果你需要字符串(由@Hamish建议):
var set = Set<String>()
let orderedSet: [String] = array.flatMap {
guard let string = numberFormatter.string(for: $0) else { return nil }
return set.insert(string).inserted ? string : nil
}
orderedSet // ["0.750", "0.005", "0.004"]
答案 2 :(得分:0)
你的问题有点复杂,因为你的双打等式是基于在小数点后的前三位数。许多线程描述了删除重复的地方,其中简单的相等适用,但我找不到包含双打的问题,并在你的问题中进行比较。
您通常使用Set
来消除重复项,但Set<Double>
使用不符合您要求的严格相等。
规范化值可能适用于您的情况:
extension Double {
var my_normalized: Double {
return (self * 1000).rounded() / 1000
}
}
print(0.0050000000000000001.my_normalized == 0.0051.my_normalized) //->true
使用此功能,您可以编写如下内容:
let arr = [0.75, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0050000000000000001, 0.0040000000000000001 /*,...*/]
var valueSet: Set<Double> = []
var result: [Double] = []
arr.forEach {value in
let normalizedValue = value.my_normalized
if !valueSet.contains(normalizedValue) {
valueSet.update(with: normalizedValue)
result.append(value)
}
}
print(result) //->[0.75, 0.0050000000000000001, 0.0040000000000000001]
如果您不介意结果的顺序并且它可以包含规范化值,则代码可以更简单:
let simpleResult = Array(Set(arr.map {$0.my_normalized}))
print(simpleResult) //->[0.75, 0.0050000000000000001, 0.0040000000000000001]