Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何简化此Swift排序代码?_Swift_Sorting - Fatal编程技术网

如何简化此Swift排序代码?

如何简化此Swift排序代码?,swift,sorting,Swift,Sorting,我正在用自己的数据处理一个问题。我已经到了编写排序函数的地步,这就是我想到的: var payment_list: [Payment]! func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) { guard let sortDescriptor = tableView.sortDescriptors.first else {

我正在用自己的数据处理一个问题。我已经到了编写排序函数的地步,这就是我想到的:

var payment_list: [Payment]!

func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) {
    guard let sortDescriptor = tableView.sortDescriptors.first else {
        return
    }

    let key = sortDescriptor.key!

    if sortDescriptor.ascending == true {
        if key == "id" {
            payment_list.sort { $0.id < $1.id }
        } else if key == "msatoshi" {
            payment_list.sort { $0.msatoshi < $1.msatoshi }
        } else if key == "created_at" {
            payment_list.sort { $0.created_at < $1.created_at }
        } else if key == "status" {
            payment_list.sort { $0.status < $1.status }
        }
    } else {
        if key == "id" {
            payment_list.sort(by: { $0.id > $1.id })
        } else if key == "msatoshi" {
            payment_list.sort { $0.msatoshi > $1.msatoshi }
        } else if key == "created_at" {
            payment_list.sort { $0.created_at > $1.created_at }
        } else if key == "status" {
            payment_list.sort { $0.status > $1.status }
        }
    }

    tableView.reloadData()
}
我得到的印象是,在Swift开发中,有很多巨大的嵌套if…else if和/或switch…case块。这是准确的评估吗

更新:

这是我的付款定义:

struct Payment: Codable, PaymentFactory {
    let id: Int
    let payment_hash: String
    let destination: String
    let msatoshi: Int
    let timestamp: Int
    let created_at: Int
    let status: String

    enum PaymentKeys: String, CodingKey {
        case payments
    }

    static func fake() -> Payment {
        // snipped for brevity
    }
}
添加一个枚举来处理各种排序描述符键怎么样?然后,您可以向Payment类添加一个函数,该函数根据传入的枚举值返回正确的属性,这使得实际的排序函数非常简洁

例如,如果所有属性都是int,则可以执行以下操作:

enum Key: String {
    case id = "id", amount = "amount", createdAt = "createdAt", status = "status"
}

class Payment {

  let id: Int
  let amount: Int
  let createdAt: Int
  let status: Int

  func attribute(forKey key: Key) -> Int {
    switch key {
    case .id: return self.id
    case .amount: return self.amount
    case .createdAt: return self.createdAt
    case .status: return self.status
    }
  }

}
enum Key: String {
    case id = "id", amount = "amount", createdAt = "createdAt", status = "status"
}

class Payment {

    let id: Int
    let amount: Int
    let createdAt: Int
    let status: String

    func compare(toOther other: Payment, byKey key: Key, ascending: Bool) -> Bool {
        switch key {
        case .id:
            return ascending ? self.id < other.id : self.id > other.id
        case .amount:
            return ascending ? self.amount < other.amount : self.amount > other.amount
        case .createdAt:
            return ascending ? self.createdAt < other.createdAt : self.createdAt > other.createdAt
        case .status:
            return ascending ? self.status < other.status : self.status > other.status
        }
    }
}
let sortDescriptor = NSSortDescriptor(key: "amount", ascending: true)

let key = Key(rawValue: sortDescriptor.key!)!

paymentList.sort(by: { $0.compare(toOther: $1, byKey: key, ascending: sortDescriptor.ascending) })
当需要排序时,您可以这样做:

let key = Key(rawValue: sortDescriptor.key!)!

if sortDescriptor.ascending {
  paymentList.sort(by: { $0.attribute(forKey: key) < $1.attribute(forKey: key) })
} else {
  paymentList.sort(by: { $0.attribute(forKey: key) > $1.attribute(forKey: key) })
}
这将使您的排序如下所示:

enum Key: String {
    case id = "id", amount = "amount", createdAt = "createdAt", status = "status"
}

class Payment {

  let id: Int
  let amount: Int
  let createdAt: Int
  let status: Int

  func attribute(forKey key: Key) -> Int {
    switch key {
    case .id: return self.id
    case .amount: return self.amount
    case .createdAt: return self.createdAt
    case .status: return self.status
    }
  }

}
enum Key: String {
    case id = "id", amount = "amount", createdAt = "createdAt", status = "status"
}

class Payment {

    let id: Int
    let amount: Int
    let createdAt: Int
    let status: String

    func compare(toOther other: Payment, byKey key: Key, ascending: Bool) -> Bool {
        switch key {
        case .id:
            return ascending ? self.id < other.id : self.id > other.id
        case .amount:
            return ascending ? self.amount < other.amount : self.amount > other.amount
        case .createdAt:
            return ascending ? self.createdAt < other.createdAt : self.createdAt > other.createdAt
        case .status:
            return ascending ? self.status < other.status : self.status > other.status
        }
    }
}
let sortDescriptor = NSSortDescriptor(key: "amount", ascending: true)

let key = Key(rawValue: sortDescriptor.key!)!

paymentList.sort(by: { $0.compare(toOther: $1, byKey: key, ascending: sortDescriptor.ascending) })
如果您的付款类型是NSObject,则可以使用@objc标记数据字段,并使用NSSortDescriptor的内置比较功能。它甚至可以自动处理升序/降序

工作区代码段:

import Foundation

class Payment: NSObject {
    @objc var id: String
    @objc var amount: Double
    @objc var created_at: Date
    @objc var status: String

    init(id: String, amount: Double, created_at: Date, status: String) {
        self.id = id
        self.amount = amount
        self.created_at = created_at
        self.status = status
        super.init()
    }
}

let arr: [Payment] = [
    Payment(id: "1", amount: 123, created_at: Date(), status: "abc"),
    Payment(id: "5", amount: 123, created_at: Date(), status: "abc"),
    Payment(id: "4", amount: 123, created_at: Date(), status: "abc"),
    Payment(id: "2", amount: 123, created_at: Date(), status: "abc")
]

let sd = NSSortDescriptor(key: "id", ascending: true)

let sorted = arr.sorted { sd.compare($0, to: $1) == .orderedAscending }

dump(sorted)

确切地说,为什么不使用switch构造呢?switch与if…else的首选项不会改变代码的总体详细程度。它实际上会使用标准格式添加八行代码。您的支付类是什么样子的?你所有的属性都是什么类型的?你检查key的值,它可以有一个不同的值。我认为控制语句是你使用Swift 4的唯一方法?这与我要寻找的非常接近,但我的对象中也有字符串。我已经更新了问题。@BenHarold查看我的编辑。我并没有为我的示例添加所有关键点,但这很有效。