按数组中的对象分组

时间:2015-12-21 14:23:16

标签: ios arrays swift swift2 grouping

我有两个对象。一个名为EstimateItem,另一个称为PartPart类继承自Realm的Object类。一个EstimateItem可以有多个Part s。

class EstimateItem {
    var parts: [Part]?
}

在每个实例中都有EstimateItem个数组Part s。

+--------------------------------+---------------------------------+
|         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)元组的数组中。< / p>

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

然后分组。

但我还是被困住了。此外,我觉得我过度复杂,我想知道是否有更简单,更实际的 Swifty 方法。

1 个答案:

答案 0 :(得分:3)

我想要找到更多 swifty 这样做的方法如下:

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或相关内容 - 在我的测试中,我只让部分继承自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
}