0

Given I have array of stucts like this:

let array = [Struct(key: "a", value: 1), Struct(key: "b", value:2)]

How can I subscript the array with the key?

array["b"] would be nice, but as expected, it doesn't work.

Edit: The reason I'm not using dictionary, is I need to preserve the order of items.

1
  • make it array of dictionary Commented Jul 19, 2017 at 11:03

4 Answers 4

5

This is syntactic sugar around your solution, @AdamBardon.

You can extend Array to allow you to subscript it directly. Under the covers it is just using the same first(where:) call:

protocol HasKey {
    var key: String { get }
}

struct Struct: HasKey {
    var key: String
    var value: Int
}

extension Array where Element: HasKey {
    subscript(str: String) -> Element? {
        return self.first(where: { $0.key == str })
    }
}

Example:

let array = [Struct(key: "a", value: 1), Struct(key: "b", value:2)]

if let x = array["a"] {
    print(x)
}

Output:

Struct(key: "a", value: 1)

Using the protocol allows you to easily extend this functionality to any class or struct that has a key: String property by having them adopt the HasKey property:

extension SomeOtherClass: HasKey { }

You can also accomplish it without the protocol by checking if Element == Struct:

extension Array where Element == Struct {
    subscript(str: String) -> Element? {
        return self.first(where: { $0.key == str })
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is exactly what I've been looking for! :) Thank you
2

You can make the dictionary of dictionaries like below code:

let myDictionaryOfDictionaries : [String : [String : String]] =
["Apples" : ["Colour" : "Red", "Type" : "Granny Smith"],
 "Oranges" : ["Colour" : "Orange", "Type" : "Seville"]]

print(myDictionaryOfDictionaries["Apples"] ?? "")

Hope it will help you.

1 Comment

I've just edited my question, the reason I'm not using dictionary, is I need to preserve the order of items.
1

You should use a dictionary. Arrays are designed to access elements by their index and not by a property of the element. Indexes also have to be integers.

Dictionaries on the other hand are key-value pairs, so using a Dictionary seems to perfect for your use case. let structs = ["a":Struct(key:"a",value:1),"b":Struct(key:"b",value:2)] structs["b"] returns the struct with key "b".

3 Comments

Yes, dictionary was my first choice, however I need to preserve the order
In most cases it is easier to get around the issue of a Dictionary being unordered than trying to access elements of an Array with a non integer index. What are you exactly trying to do for which you need ordering?
The context is too complex to be explained here, but anyway I have an alternative. I'll provide it as answer as it solves my problem. Nonetheless thanks for help.
1

This is not the exact way how I imagined the solution, but it's a good alternative which solves my problem.

I got what I needed using this: array.first(where: { $0.key == "b" })

Comments

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.