在数组中按对象分组

3
我有两个对象,一个叫做EstimateItem,另一个叫做PartPart类是继承自Realm的Object类)。一个EstimateItem可以有多个Part
class EstimateItem {
    var parts: [Part]?
}

有一个EstimateItem数组,每个实例中的Part数量不同。

+--------------------------------+---------------------------------+
|         EstimateItem           |            Parts                |
+--------------------------------+---------------------------------+
| Line Item 1 - RnR WDH - Twins  |  Epoxy / Wood for lami          |
| (single)                       |                                 |
|                                |                                 |
| Line Item 2 - RnR WDH - Twins  |  Epoxy / Wood for lami          |
| (double)                       |                                 |
|                                |                                 |
|Line Item 3 - Install sash lock |Epoxy / Wood for lami / Sash lock|
+--------------------------------+---------------------------------+

我需要按照特定的 Part 对它们进行分组。应该长成这个样子。

enter image description here

我该怎么做?

当部件附加到单个项目时,我无法想出一种方法来完成此操作,因此我尝试将它们全部排列在一个(part: Part, item: EstimateItem)元组数组中。

var groups = [(part: Part, item: EstimateItem)]()
for item in estimateItemsArray {
    if let parts = item.parts {
        for part in parts {
            groups.append((part, item))
        }
    }
}

// Epoxy - RnR WDH - Twins (single)
// Wood for lami - RnR WDH - Twins (single)
// Epoxy - RnR WDH - Twins (double)
// Wood for lami - RnR WDH - Twins (double)
// Epoxy - RnR WDH - Twins (single)
// Wood for lami - RnR WDH - Twins (single)
// Sash lock, traditional - Install sash lock

然后将其分组。

但我仍然卡住了。而且我觉得我过于复杂化了,想知道是否有更简单、更符合Swift风格的方法来完成这个任务。


我可以假定您拥有所有部件和项目的数组吗?像 var parts : [Part] 这样? - luk2302
@luk2302 没有单独的部件数组。有一个名为estimateItemsArray的项目数组。在每个项目中,都有像您提到的部件数组。 - Isuru
1个回答

3

我尝试寻找更加迅速的方法来完成这个任务,想到了以下方案:

let parts = Set(estimateItemsArray.flatMap{ $0.parts ?? [] })

let partMap = parts.map { part in
    return (part, estimateItemsArray.filter {
            $0.parts?.indexOf(part) != nil
        }
    )
}

partMap现在包含形如(Part,[EstimateItem])的元组。唯一的要求是Part符合Hashable或者相关的东西 - 在我的测试中,我只让Part继承自NSObject

解释:

  • 创建一个包含所有可用部件的数组(使用Set确保唯一性)
  • 循环遍历该数组,映射并返回一个元组,其中包括
    • 实际的部件
    • 循环遍历estimateItemsArray,过滤掉其列表中包含当前部件的项目

完整的测试数据如下所示

/* the now classes, both include some identifier to distinguish them */
class Item {
    var n : String
    var parts : [Part]? = [Part]()
    init(n:String) {
        self.n = n
    }
}

class Part : NSObject {
    var n : String
    init(n:String) {
        self.n = n
    }
}

/* set up the test data */
let item1 = Item(n: "item 1")
let item2 = Item(n: "item 2")
let item3 = Item(n: "item 3")

let part1 = Part(n: "part 1")
let part2 = Part(n: "part 2")
let part3 = Part(n: "part 3")

item1.parts = [part1, part2]
item2.parts = [part1, part3]
item3.parts = [part1, part2, part3]

var arrItems = [item1, item2, item3]

/* actual logic */
let parts = Set(arrItems.flatMap{ $0.parts ?? [] })

let partMap = parts.map { part in
    return (part, arrItems.filter {
            $0.parts?.indexOf(part) != nil
        }
    )
}

/* final output */
partMap.forEach { entry in
    print("part \(entry.0.n)")
    entry.1.forEach {
        print("contains \($0.n)")
    }
}

输出:

部分1
包含项目1
包含项目2
包含项目3
部分3
包含项目2
包含项目3
部分2
包含项目1
包含项目3

如果您无法像我最初想的那样从NSObject继承,请使您的类Part符合集合所需的Hashable协议:

class Part : Hashable {
    var n : String
    init(n:String) {
        self.n = n
    }

    var hashValue: Int {
        return n.hashValue // you basically have to provide some kind of logic based on *your* Part object
    }
}

func ==(lhs: Part, rhs: Part) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

谢谢你的回答。不幸的是,出现了一个问题。我正在使用Realm,并且Part类是从Realm自己的Object类继承的,无法修改为继承自NSObject。很抱歉在我的问题中没有提到这一点。所以我在第一行代码上遇到了错误**Cannot invoke initializer for type 'Set<_>' with an argument list of type '([Part])'**。有没有什么解决办法? - Isuru
这很奇怪,因为Realm的Object类是从一个叫做RLMObjectBase的类继承而来,而这个类本身是从NSObject继承而来的。但尽管如此,我仍然遇到了那个错误。 - Isuru
@Isuru 我正在购物,现在会立即查看它。 - luk2302
@Isuru 我更新了我的答案 - 我不知道 Realm 会如何反应,也许已经有一个 hashValue 实现或者一个 == 的实现! - luk2302

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接