0

I have an array as followed:

let arr = [InventoryItem(capacity: "1T", chainLength: 55, speed: "32FPM", voltage: "110V", frameSize: "Small", controlStation: "None"),
       InventoryItem(capacity: "1T", chainLength: 55, speed: "32FPM", voltage: "110V", frameSize: "Small", controlStation: "None"),
       InventoryItem(capacity: "1T", chainLength: 55, speed: "32FPM", voltage: "110V", frameSize: "Small", controlStation: "None"),
       InventoryItem(capacity: "1T", chainLength: 55, speed: "32FPM", voltage: "110V", frameSize: "Small", controlStation: "None"),
       InventoryItem(capacity: "1T", chainLength: 55, speed: "32FPM", voltage: "110V", frameSize: "Small", controlStation: "None"),
       InventoryItem(capacity: "1/2T", chainLength: 65, speed: "16FPM", voltage: "208V", frameSize: "Standard", controlStation: "Integrated"),
       InventoryItem(capacity: "1/2T", chainLength: 65, speed: "16FPM", voltage: "208V", frameSize: "Standard", controlStation: "Integrated"),
       InventoryItem(capacity: "1/2T", chainLength: 65, speed: "16FPM", voltage: "208V", frameSize: "Standard", controlStation: "Integrated"),
       InventoryItem(capacity: "1/2T", chainLength: 65, speed: "16FPM", voltage: "208V", frameSize: "Standard", controlStation: "Integrated")]

I want to group them into other array or dictionary where all of the elements have same attributes. Is there way to do it?

5
  • you can filter them on basis of any property Commented Jun 28, 2018 at 7:51
  • yeah but I can only filter by one property, all of the properties have to be same Commented Jun 28, 2018 at 7:52
  • try Comparable protocol and compare complete model and filter them accordingly Commented Jun 28, 2018 at 8:10
  • I would suggest Equatable as we need only the == operation. And then you could filter them Commented Jun 28, 2018 at 8:22
  • you can use NSPredicate for comparing with multiple fields. Please refer NSpredicate and NSCompoundPredicate Commented Jun 28, 2018 at 10:19

1 Answer 1

3

You can adopt to this example by conforming InventoryItem to Equatable and Hashable as below,

class InventoryItem: Equatable, Hashable {

    var hashValue: Int { return a.hashValue ^ b.hashValue ^ c.hashValue }

    static func == (lhs: InventoryItem, rhs: InventoryItem) -> Bool {
        return  lhs.a == rhs.a &&
                lhs.b == rhs.b &&
                lhs.c == rhs.c
    }

    var a: String
    var b: String
    var c: String

    init(_ a: String, b: String, c: String) {
        self.a = a
        self.b = b
        self.c = c
    }
}

Lets say we have this data,

let inv1 = InventoryItem("a", b: "b", c: "c")
let inv2 = InventoryItem("a", b: "b", c: "c")
let inv3 = InventoryItem("p", b: "q", c: "r")
let inv4 = InventoryItem("x", b: "y", c: "z")
let list = [inv1, inv2, inv3, inv4]

var groupedItems: [String: [InventoryItem]] = [:]

let unique = Set(list)
unique.forEach { (item) in
   groupedItems["\(item.hashValue)"] = list.filter({ $0 == item })
}

groupedItems.keys.forEach { key in
   let items = groupedItems[key]!
   print(items.count)
   items.forEach({ (item) in
       print("\(item.a)\(item.b)\(item.c)")
   })
}

Output:

1
xyz
1
pqr
2
abc
abc

Note If your InventoryItem is a struct or enum then you don't need to explicitly conform to Equatable, only conforming to Hashable is enough and you can just remove hashValue and equator method(static func == (lhs: InventoryItem, rhs: InventoryItem) -> Bool) from InventoryItem.

Sign up to request clarification or add additional context in comments.

1 Comment

in that case I should know the object to compare with others. I need a solution to automatically group same objects where I know nothing about them

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.