代码之家  ›  专栏  ›  技术社区  ›  brandonscript

基于与特定属性对应的另一个数组中的值对对象数组进行排序

  •  0
  • brandonscript  · 技术社区  · 10 年前

    假设从JSON API中检索对象数组:

    [
        {
            "id": 48,
            "name": "Bob"
        },
        {
            "id": 198,
            "name": "Dave"
        },
        {
            "id": 2301,
            "name": "Amy"
        },
        {
            "id": 990,
            "name": "Colette"
        }
    ]
    
    // e.g. for ease of reproduction:
    
    let dataObjects = [
        ["id": 48, "name": "Bob"], 
        ["id": 198, "name": "Dave"], 
        ["id": 2301, "name": "Amy"], 
        ["id": 990, "name": "Colette"]
    ]
    

    在客户端上,我希望允许用户重新排序这些对象。为了保存订单,我将在数组中存储一个id列表:

    let index: [Int] = [48, 990, 2103, 198]
    

    如何根据排序索引中id的顺序对原始数据对象数组重新排序?

    dataObjects.sort({ 
        // magic happens here maybe?
    }
    

    所以最后,我得到:

    print(dataObjects)
    /* 
    [
        ["id": 48, "name": "Bob"], 
        ["id": 990, "name": "Colette"], 
        ["id": 2301, "name": "Amy"], 
        ["id": 198, "name": "Dave"]
    ]
    /*
    
    3 回复  |  直到 10 年前
        1
  •  2
  •   Aviel Gross Verticon    10 年前

    方法A) 将数据解析为一个简单的字典,其中字典的键是用于对其进行排序的id:

    func sort<Value>(a: [Int: Value], basedOn b: [Int]) -> [(Int, Value)] {
        return a.sort { x, y in
            b.indexOf(x.0) < b.indexOf(y.0)
        }
    }
    
    // ....
    let a = [48:"Bob", 198:"Dave", 2301:"Amy", 990:"Colette"]
    let b = [48, 198, 2301, 990]
    sort(a, basedOn: b)
    

    方法B) 有一些习惯 DataObject 类型:(可能是最好的方式)

    struct DataObject {
        let id: Int
        let name: String
    
        init(_ id: Int, _ name: String) {
            self.id = id
            self.name = name
        }
    }
    
    func sort(a: [DataObject], basedOn b: [Int]) -> [DataObject] {
        return a.sort { x, y in
            b.indexOf(x.id) < b.indexOf(y.id)
        }
    }
    
    
    let a = [DataObject(48, "Bob"), DataObject(198, "Dave"), DataObject(2301, "Amy"), DataObject(990, "Colette")]
    let b = [48, 198, 2301, 990]
    
    sort(a, basedOn: b)
    /* [
         DataObject(id: 48, name: "Bob"), 
         DataObject(id: 990, name: "Colette"), 
         DataObject(id: 198, name: "Dave"), 
         DataObject(id: 2301, name: "Amy")
    ] */
    

    方法C) 使用 未经加工的 json值,可以用一种不那么“干净”的方式完成:

    func sort<Value>(a: [[String: Value]], basedOn b: [Int]) -> [[String: Value]] {
        return a.sort { x, y in
            let xId = x["id"] as! Int
            let yId = y["id"] as! Int
            return b.indexOf(xId) < b.indexOf(yId)
        }
    }
    
    let dataObjects = [
        ["id": 48, "name": "Bob"],
        ["id": 198, "name": "Dave"],
        ["id": 2301, "name": "Amy"],
        ["id": 990, "name": "Colette"]
    ]
    
    let b = [48, 198, 2301, 990]
    
    sort(dataObjects, basedOn: b)
    
        2
  •  2
  •   Community Mohan Dere    5 年前

    您可以利用Swift提供的功能支持,并使用 map 函数迭代 index 数组并获取相应的对象:

    let sortedObjects = index.map{ id in
        dataObjects.filter{ $0["id"] as? Int == id }.first
    }
    

    这假设 指数 在映射数据对象之前正确计算数组。


    编辑

    感谢用户3441734 flatMap 建议。这是一个利用它的解决方案,基本上它只是被替换了 地图 通过 平面地图 为了摆脱可能 nil 并将结果数组转换为非选项数组。

    let sortedObjects = index.flatMap{ id in
        dataObjects.filter{ $0["id"] as? Int == id }.first
    }
    

    如果为空 指数 如果保持相同的顺序,那么我们可以简单地进行测试:

    let sortedObjects = index.count > 0 ? index.flatMap{ id in
        dataObjects.filter{ $0["id"] as? Int == id }.first
    } : dataObjects
    
        3
  •  1
  •   Victor Sigler    10 年前

    您不需要保留带有索引的数组,您可以根据需要的对象进行排序,假设您具有以下结构:

    struct DataObject {
       var id: Int
       var name: String
    }
    
    var data = [DataObject]()
    data.append(DataObject(id: 48, name: "Bob"))
    data.append(DataObject(id: 198, name: "Dave"))
    data.append(DataObject(id: 2301, name: "Amy"))
    data.append(DataObject(id: 990, name: "Colette"))
    

    您可以使用 sort 函数对结果进行排序并返回其他数组或 sorted 功能,如果您想使其就位

    // ordered by id
    var sortedData = data.sort { index.indexOf($0.id) < index.indexOf($1.id) }
    

    我希望这能帮助你。