给定一个定义如下的数组
let list: [Any]
我想WHEN对其进行排序
- 其中的所有值都具有相同的类型
Element
- AND
Element
是Comparable
。
什么时候应该返回排序后的数组
所以我需要一个函数,当数组以如下方式填充时
let list: [Any] = [10, 11, 0, 2, -1]
let list: [Any] = ["Red", "Green", "Blue"]
let list: [Any] = [true, false, true, true]
确实返回排序后的数组。
什么时候应该返回nil
另一方面,当 list
包含以下示例之一时
let list: [Any] = [CGPointZero, CGPoint(x:1, y:1)] // CGPoint is not comparable
let list: [Any] = [10, "Hello"] // Values of different types
我想要 nil
作为返回值。
有什么想法吗?
最佳答案
编译时解决方案
extension _ArrayType where Generator.Element == Any {
func sortQ() -> Any? {
return nil
}
}
extension _ArrayType where Generator.Element: Comparable {
func sortQ() -> [Self.Generator.Element] {
return self.sort(<)
}
}
// Because Bool is not comparable by default...
extension Bool: Comparable {
}
public func < (lhs: Bool, rhs: Bool) -> Bool {
return !lhs && rhs // or Int(lhs) < Int(rhs)
}
[10, 11, 0, 2, -1].sortQ() //[-1, 0, 2, 10, 11]
["Red", "Green", "Blue"].sortQ() //["Blue", "Green", "Red"]
[true, false, true, true].sortQ() //[false, true, true, true]
[CGPointZero, CGPoint(x:1, y:1)].sortQ() //nil
[10, "Hello"].sortQ() //nil
运行时解决方案:
更新
这里是非最终状态。问题在于类型转换可比较。恕我直言,这是不可能的。直到现在我还不知道可选类型的技巧。无论如何,甚至无法转换元类型,因为直到运行时才知道类型。我的弱解决方法是列出支持的可比类型:
extension _ArrayType {
func sortQ() -> [Generator.Element]? {
var arrayOK = true
let sortedArray = sort { (firstElement, secondElement) -> Bool in
guard arrayOK else {
return false
}
let f = Mirror(reflecting: firstElement)
let s = Mirror(reflecting: secondElement)
guard f.subjectType == s.subjectType else {
arrayOK = false
return false
}
switch String(f.subjectType) {
case "Int":
return (firstElement as! Int) < (secondElement as! Int)
case "String":
return (firstElement as! String) < (secondElement as! String)
case "Bool":
return (firstElement as! Bool) < (secondElement as! Bool)
default:
arrayOK = false
return false
}
}
return arrayOK ? sortedArray : nil
}
}
更新 2
第二个选项是以不同方式定义可比协议(protocol) (AnyComparable
)。不幸的是,这意味着为所有 Comparable 类型创建扩展。
否则,编译器无法在编译时找到正确的函数/运算符(因为它无法提前知道类型)。
所以你有两个选择:
- 如果你对你正在比较和定义的类型有一些了解 他们明确地(更新1)。
- 使用不使用Self的接口(interface) 输入(更新 2)。
恕我直言,没有其他解决方案
protocol AnyComparable {
func compareTo(second: Any) -> Bool
}
extension AnyComparable where Self: Comparable {
func compareTo(second: Any) -> Bool {
if let secondSameType = second as? Self {
return self < secondSameType
}
return false
}
}
extension Int: AnyComparable {
}
extension String: AnyComparable {
}
extension Bool: AnyComparable {
}
extension _ArrayType {
func sortQ() -> [Generator.Element]? {
var arrayOK = true
var wantedType: Any.Type?
let sortedArray = sort { (firstElement, secondElement) -> Bool in
guard arrayOK else {
return false
}
if wantedType == nil {
wantedType = Mirror(reflecting: firstElement).subjectType
}
guard let f = firstElement as? AnyComparable where wantedType == Mirror(reflecting: secondElement).subjectType else {
arrayOK = false
return false
}
return f.compareTo(secondElement)
}
return arrayOK ? sortedArray : nil
}
}
关于arrays - 对 [Any] 数组进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38153215/