Agrupar por un object en una matriz

Tengo dos objects Uno llamado EstimateItem y el otro se denomina Part (la class de Part se henetworkinga de la class Object del reino). Un EstimateItem puede tener múltiples Part .

 class EstimateItem { var parts: [Part]? } 

Hay una variedad de EstimateItem con diferentes numbers de Part en cada instancia.

 +--------------------------------+---------------------------------+ | 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| +--------------------------------+---------------------------------+ 

Necesito agruparlos por una Part específica. Debería parecer algo así.

introduzca la descripción de la imagen aquí

¿Cómo hago esto?

No pude encontrar una manera de hacer esto mientras las partes están unidas a un elemento individual, así que intenté distribuirlas en una variedad de tuplas (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 

Y luego agruparlo.

Pero todavía estoy atrapado. También siento que estoy complicado y me preguntaba si hay una manera más fácil y más Swifty de hacer esto.

Lo que surgió al tratar de encontrar una manera más rápida de hacer esto es lo siguiente:

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

partMap ahora contiene tuplas del formulario (Part, [EstimateItem]) . El único requisito es que la Part ajuste a Hashable o algo relacionado: en mi testing, solo dejo que parte henetworkinge de NSObject .

Explicación:

  • cree una matriz de todas las partes disponibles ( Set para garantizar la exclusividad)
  • bucle sobre la asignación de matriz y devuelve una tupla de
    • la parte real
    • loop over estimateItemsArray filtra los elementos que tienen la parte actual en su list

La testing completa de datos se parece a esto

 /* 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)") } } 

Salida:

parte parte 1
contiene el ítem 1
contiene el artículo 2
contiene el ítem 3
parte parte 3
contiene el artículo 2
contiene el ítem 3
parte parte 2
contiene el ítem 1
contiene el ítem 3

Si no puede henetworkingar de NSObject como, sin embargo, inicialmente, haga que su class Part ajuste a Hashable que es el requisito para sets:

 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 } 
Intereting Posts