我有一个像这样的对象数组,但有16个属性:
class anObject: NSObject {
@objc var number: Int
@objc var name: String
@objc var price: Double
subscript(key: String) -> Any? {
return self.value(forKey: key)
}
}
我可以很容易地在任何属性上对数组进行排序,例如:
sortedArray = unsortedArray.sorted(by: { $0.name < $1.name } )
现在我正在对我的数组进行分组,以便我可以使用节和行填充UITableView。我这样分组:
var groupedArray = Dictionary<String, Array<myObject>>()
for item in myArray {
// Verify each grouping is initialized only once
if groupedArray[item[byProperty] as! String] == nil {
groupedArray[item[byProperty] as! String] = Array<Items>()
}
// Add the item into the correct subarray
groupedArray[item[byProperty] as! String]?.append(item)
}
然后,我可以通过执行以下操作对分组数组进行排序:
return groupedArray.sorted { $0.0 < $1.0 }
这很有效,除了我的两个属性是双打。当我对这两个属性进行排序时,Swift按字母顺序对组进行排序:
10.5, 11.5, 12, 1.5, 2.0 . . .
而不是数字
1.5, 2.0, 10.5, 11.5, 12 . . .
我设法通过检查它们是否太短并在String的前面插入0来填充双打。这样做的原因在于它们现在按正确的顺序排序,但最终我将不得不从前面剥离前导0,这似乎是一个丑陋的解决方案。
如果双打必须用作字符串,我如何正确对分组数组进行排序?
答案 0 :(得分:0)
当您开始在整个地方投射字符串时,您可能需要开始更改设计。为什么不使字典键成为你设计的对象而不是字符串呢?这是我的意思的样本:
struct DoubleKey {
let value: Double
}
extension DoubleKey: Hashable {
var hashValue: Int {
return value.hashValue
}
static func ==(lhs: DoubleKey, rhs: DoubleKey) -> Bool {
return lhs.value == rhs.value
}
}
extension DoubleKey: Comparable {
static func <(lhs: DoubleKey, rhs: DoubleKey) -> Bool {
return lhs.value < rhs.value
}
}
let a = DoubleKey(value: 10.0)
let b = DoubleKey(value: 20.0)
let c = DoubleKey(value: -10.0)
let dictionary: [DoubleKey: String] = [a: "10", b: "20", c: "-10"]
let sortedDictionary = dictionary.sorted { $0.0 < $1.0 }
因此,[String: Array<myobject>]
或[DoubleKey: Array<MyObject>
或[IntegerKey: Array<MyObject>]
[StringKey: Array<MyObject>
您可以实现自己专用密钥的许多变体,并在需要其他功能时编写一些协议。如果你需要在你的密钥中存储一个字符串,那么添加一个属性,或者更好的是,使它符合一个协议,该协议定义你需要的行为并实现它。
附加密钥
struct StringKey {
let value: String
}
extension StringKey: Hashable {
var hashValue: Int {
return value.hashValue
}
static func ==(lhs: StringKey, rhs: StringKey) -> Bool {
return lhs.value == rhs.value
}
}
extension StringKey: Comparable {
static func <(lhs: StringKey, rhs: StringKey) -> Bool {
return lhs.value < rhs.value
}
}
let a = StringKey(value: "a")
let b = StringKey(value: "c")
let c = StringKey(value: "b")
let dictionary: [StringKey: String] = [a: "10", b: "20", c: "-10"]
let sortedDictionary = dictionary.sorted { $0.0 < $1.0 }
现在是什么?
//EXAMPLE
protocol ViewableString {
func view() -> String
}
extension StringKey: ViewableString {
func view() -> String {
return value
}
}
extension DoubleKey: ViewableString {
func view() -> String {
return String(value)
}
}
let array: [ViewableString] = [a, b, c]
array[0].view()
编写协议程序!
希望这有帮助!
答案 1 :(得分:0)
确定。完全不同的答案。同样,您试图在同一容器中容纳不同类型的许多对象。这对我来说是一个坏主意。也许你必须这样做。但这是使用枚举的一种方式:
enum SpecialKey {
case integer(Int)
case double(Double)
case string(String)
func asString() -> String {
switch self {
case let .integer(a):
return String(a)
case let .double(a):
return String(a)
case let .string(a):
return a
}
}
}
extension SpecialKey: Comparable {
static func <(lhs: SpecialKey, rhs: SpecialKey) -> Bool {
switch (lhs, rhs) {
case let (.double(a), .double(b)):
return a < b
case let (.integer(a), .integer(b)):
return a < b
case let (.string(a), .string(b)):
return a < b
default:
return false //Add more cases with different comparisons!
}
}
static func ==(lhs: SpecialKey, rhs: SpecialKey) -> Bool {
switch (lhs, rhs) {
case (.integer(_), .integer(_)),
(.double(_), .double(_)),
(.string(_), .string(_)):
return true
default:
return false
}
}
}
extension SpecialKey: Hashable {
var hashValue: Int {
switch self {
case let .integer(a):
return a.hashValue
case let .double(a):
return a.hashValue
case let .string(a):
return a.hashValue
}
}
}
let a = SpecialKey.integer(10)
let b = SpecialKey.string("something")
let c = SpecialKey.double(10.5)
let dictionary: [SpecialKey: String] = [a: "a", b: "b", c: "c"]
这可能更像你正在寻找的东西。