2

I want to sort an Array of objects, by the properties it shares with another Array of objects

    struct GeneralComposition : Decodable {
        let id, formId, relationId, fixedContentTypeId, separatorId: Int
        let orderBy: Int

    }
    struct FixedContentType: Decodable {
        let name, htmlType: String
        let isEditable: Int
        let typeId : String


    }



   var fixedContentType = [FixedContentType]()
   var generalComposition = [GeneralComposition]()

In GeneralComposition I get the order the items must have, with orderBy, and then take every item's fixedContentTypeID, compare with the typeId in FixedContentType to get the order in which this content must be showed in screen.

Any idea about how can it be done?

Thanks!

emelagumat
  • 301
  • 2
  • 10
  • Sorry, Can you show us how do you want to get an output? – Ahmet Sina Ustem Mar 15 '19 at 23:37
  • @matt - That looks like a duplicate, but isn’t quite the same. That `indexOf` pattern is not applicable here. – Rob Mar 16 '19 at 14:00
  • Cosorting is cosorting it seems to me. It’s not like it’s never been discussed before. – matt Mar 16 '19 at 14:02
  • Maybe, we can find a consorting example where it’s not relying on the `index(of:)` the identifier in the second array, but rather a property of the objects in that second array, like this one. I looked and one didn’t jump out at me, but I bet there’s one out there... – Rob Mar 16 '19 at 14:30

1 Answers1

4

You can build a dictionary for the fixedContentTypeID’s of generalComposition:

let order = generalComposition.reduce(into: [Int: Int]()) { result, value in
    result[value.fixedContentTypeId] = value.orderBy
}

You now have an efficient way to lookup the orderBy value for a given typeId within your array of FixedContentType objects. You can use that for sorting:

fixedContentType.sort {
    (order[$0.typeId] ?? 0) < (order[$1.typeId] ?? 0)
}

By the way, your typeId is a String, and fixedContentTypeId is an Int. I’m assumed that was a typo introduced when preparing the question, and that they’re really both Int. If they’re really different types (which would be weird), the solution would be similar, though you’d have to do some conversions. But I didn’t want to go there unless you confirmed that this is really what you model was.

But, given that your typeId really is a String, you could make your dictionary a [String: Int]:

let order = generalComposition.reduce(into: [String: Int]()) { result, value in
     result[String(value.fixedContentTypeId)] = value.orderBy
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • What about a protocol ? – Mohmmad S Mar 16 '19 at 00:46
  • make protocol that have the shared properties and an array of this protocol and sort that ? – Mohmmad S Mar 16 '19 at 01:02
  • 2
    I’d suggest you post you own answer showing how you’d propose using a protocol. I personally don’t see how that would help. The main thrust of my answer is using a dictionary to achieve O(1) performance for the retrieval of the `orderBy` values. – Rob Mar 16 '19 at 01:06
  • 1
    if i wanted to answer i would've i want to know the difference and gain exp from the high tier ^_^ thanks anyway – Mohmmad S Mar 16 '19 at 01:07
  • 1
    one day i will care about the O(1), just like you do sir. – Mohmmad S Mar 16 '19 at 01:28
  • thanks @Rob, I think this is close to be what I need, but unfortunately, they actually are different values. 'typeId' is a String which is a number, I get all this data from an API and datas come like this... So now I need to find the way to make those conversions – emelagumat Mar 16 '19 at 08:37
  • @ManuelLagunaMatias - I’ve revised my answer showing how you’d save the keys of that dictionary as `String` instances. But I’d really suggest fixing that API (or reaching out to whomever is maintaining that codebase) because it’s obviously internally inconsistent. – Rob Mar 16 '19 at 10:41