给定一个定义如下的数组
let list: [Any]
我想把它分类
>其中的所有值都具有相同的Element类型
> AND元素是可比的.
当它应该返回排序的数组
所以我需要一个函数,当数组以如下的方式填充时
let list: [Any] = [10,11,2,-1] let list: [Any] = ["Red","Green","Blue"] let list: [Any] = [true,false,true,true]
确实返回排序的数组.
当它应该返回零
另一方面,当列表包含以下示例之一时
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,-1].sortQ() //[-1,10,11] ["Red","Blue"].sortQ() //["Blue","Red"] [true,true].sortQ() //[false,true] [CGPointZero,y:1)].sortQ() //nil [10,"Hello"].sortQ() //nil
运行时解决方案:
UPDATE
这是非最终状态.问题是与铸造相当. IMHO是不可能的.到目前为止,我不知道可选类型的技巧.无论如何,即使是转换元类型也是不可能的,因为类型在运行时才是不知道的.我的弱化解决方案是列出支持的可比类型:
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
第二个选项是使可比较的协议定义不同(AnyComparable).不幸的是,这意味着创建所有可比较类型的扩展.
否则没有办法,在编译时,编译器可以找到正确的函数/运算符(因为它不提前知道类型).
所以你有两个选择:
>如果你有一些想要比较和定义的类型
他们明确(更新1).
>使用不使用Self的界面
类型(更新2).
IMHO没有其他的解决方案
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 } }