简体   繁体   中英

Sort Two Arrays of Different Types into One

I have two arrays, they are of two different objects, and both contain an ID field. What I need to do is display them in order in a table view controller. They share the same basic info, Size and ID, and those are the only pieces of data displayed, in addition to the type of object it is. When the user selects a cell then it moves to a new view that displays the finer details of the object.

Right now, I have two sections in the table, one for TypeA, and the other for TypeB. They sort through all of the items in their respective list, but are out of order for when the item was made. So it looks like:

TypeA
  ID 1
  ID 2
  ID 5
  ID 6
TypeB
  ID 3
  ID 4
  ID 7

What I need is for it to sort them all into 1 section, and still open the detail view when selected.

Thoughts

I could put them all into an AnyObject dictionary and when looking at individual items determine if they are of one object type or the other. I feel like that would work, but how would I go about sorting that correctly?

Put all common properties into a protocol, the build and sort an array of that common protocol:

protocol HasID {
    var id: Int { get }
}

class TypeA : HasID, CustomStringConvertible {
    var id: Int

    init(_ id: Int) {
        self.id = id
    }

    var description : String {
        return ("TypeA(\(self.id))")
    }
}

class TypeB : HasID, CustomStringConvertible {
    var id: Int

    init(_ id: Int) {
        self.id = id
    }

    var description : String {
        return ("TypeB(\(self.id))")
    }
}

let typeA = [TypeA(1), TypeA(2), TypeA(5), TypeA(6)]
let typeB = [TypeB(3), TypeB(4), TypeB(7)]
let result: [HasID] = (typeA + typeB).sorted { $0.id < $1.id }

print(result)
 [TypeA(1), TypeA(2), TypeB(3), TypeB(4), TypeA(5), TypeA(6), TypeB(7)] 

Alternatively to Zoff Dino answer if you do not want to burden TypeA and TypeB classes with HasID protocol then you can define extension to these classes in your view controller:

class TypeA {
    var ID: Int

    init(_ id: Int) {
        self.ID = id
    }
}

class TypeB {
    var ID: Int

    init(_ id: Int) {
        self.ID = id
    }
}

protocol HasID {
    var ID: Int { get }
}

// place this in your view controller

extension TypeA: HasID {
}

extension TypeB: HasID {
}

var arrayA = [TypeA(1), TypeA(3), TypeA(5)]
var arrayB = [TypeB(2), TypeB(4)]

let sortedArray = (arrayA.map { $0 as HasID } + arrayB.map { $0 as HasID })
                      .sort { $0.ID < $1.ID }

You can do this like so:

class TypeA {
    var ID: Int

    init(_ id: Int) {
        self.ID = id
    }
}

class TypeB {
    var ID: Int

    init(_ id: Int) {
        self.ID = id
    }
}

struct Wrap {
    var ID: Int {
        return a?.ID ?? b?.ID ?? 0
    }
    let a: TypeA?
    let b: TypeB?
}

var arrayA = [TypeA(1), TypeA(3), TypeA(5)]
var arrayB = [TypeB(2), TypeB(4)]

let sortedArray = (arrayA.map { Wrap(a: $0, b: nil) } + arrayB.map { Wrap(a: nil, b: $0)})
                      .sorted { $0.ID < $1.ID }

When row is selected you can determine object with:

if let a = sortedArray[index].a {
    // TypeA row selected
} else if let b = sortedArray[index].b {
    // TypeB row selected
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM