【问题标题】:iOS Swift Filter and Generating Model takes too much timeiOS Swift 过滤器和生成模型需要太多时间
【发布时间】:2018-07-27 08:31:30
【问题描述】:

我有 3 个模型和各自的数组

struct A {
    var id: String
    var bId: String
    var cId: String
}

struct B {
    var id: String
}

struct C {
    var id: String
}


let aList: [A] = [.......] // 100 elements

let bList: [B] = [.......] // 200 elements

let cList: [C] = [.......] // 300 elements

现在我需要 struct 'FilterModel' 的对象数组,它将通过迭代 'bList' 和 'cList' 过滤strong>aList'

struct FilterModel {

    var objA: A
    var objB: B?
    var objC: C?

    init(objA: A,
         objB: B? = nil,
         objC: C? = nil) {

         self.objA = objA
         self.objB = objB
         self.objC = objC
    }
}

So far i have tried like this


var filterModels: [FilterModel] = []

for aModel in aList {

    let filterBModel = bList.filter { $0.id == aModel.bId }.first
    let filterCModel = cList.filter { $0.id == aModel.cId }.first

    let model =  FilterModel(objA: aModel,
                             objB: filterBModel,
                             objC: filterCModel)

    filterModels.append(model)
}

是否有任何优化或更好的方法,因为它需要太多时间?

【问题讨论】:

  • 首先,将bList.filter { $0.id == aModel.bId }.first改为bList.first { $0.id == aModel.bId }。但无论如何,性能会很糟糕。
  • 从哪里得到 bList 和 cList 数组?你正在创造它们?
  • A. bId & B.id 之间有关系吗?
  • @LalKrishna:我的代码中已经提到

标签: ios arrays swift algorithm


【解决方案1】:

由于aList 的每次迭代都必须遍历两个列表,因此复杂性并不好。相反,首先生成索引:

var bIndex: [String: B] = [:]
bList.forEach {
   bIndex[$0.id] = $0
} 

var cIndex: [String: C] = [:]
cList.forEach {
   cIndex[$0.id] = $0
} 

let filterModels: [FilterModel] = aList.map { aModel in
   return FilterModel(
      objA: aModel,
      objB: bIndex[aModel.bId],
      objC: cIndex[aModel.cId]
   )
}

【讨论】:

    【解决方案2】:
    struct A {
        var id: String
        var bId: String
        var cId: String
    }
    
    struct B {
        var id: String
    }
    
    
    struct C {
        var id: String
    }
    
    let aList: [A] = [A(id: "a", bId: "b", cId: "c")] // 100 elements
    
    let bList: [B] = [B(id: "a")] // 200 elements
    
    let cList: [C] = [C(id: "a")] // 300 elements
    
    struct FilterModel {
        var objA: A
        var objB: B?
        var objC: C?
    
        init(objA: A,
             objB: B? = nil,
             objC: C? = nil) {
            self.objA = objA
            self.objB = objB
            self.objC = objC
        }
    }
    
    var finalList: [FilterModel] = []
    aList.forEach { a in
        let b = bList.first(where: { $0.id == a.id })
        let c = cList.first(where: { $0.id == a.id })
        finalList.append(FilterModel(objA: a, objB: b, objC: c))
    }
    

    如果记录是通过 API 传来的。我希望您对响应使用分页 使用紧凑型地图

     let finalList = aList.compactMap { a -> FilterModel in
            let b = bList.first(where: { $0.id == a.id })
            let c = cList.first(where: { $0.id == a.id })
            return FilterModel(objA: a, objB: b, objC: c)
        }
    

    【讨论】:

    • 每个分页不可用的地方,所以在这种情况下应该有解决方案
    • 我们不能用compactMap(以前叫flatMap)代替forEach吗?
    • @RameswarPrasad 是的,你也可以使用紧凑型地图。 let finalList = aList.compactMap { a -> FilterModel in let b = bList.first(where: { $0.id == a.id }) let c = cList.first(where: { $0.id == a.id }) return FilterModel(objA: a, objB: b, objC: c) }
    • @AjaySinghMehra 正确。这样,它将finalList 保持为常量并扩展更多功能编码。 :)
    猜你喜欢
    • 1970-01-01
    • 2017-10-05
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    相关资源
    最近更新 更多