I have a dictionary of Strings, like chapters or table of contents for an aircraft manual, like this:
let ataChapter: [[String:String]:Dictionary] = [
["21":"Air Conditioning"] : [
"21-31":"Pressure control and monitoring",
"21-51":"Pack flow control",
"21-52":"Air cooling system",
"21-55":"Emergency ram air inlet",
"21-61":"Pack temperature control",
"21-63":"Cockpit and cabin temperature control"],
["22":"Autoflight"] : [
"22-01":"Overhead panel",
"22-05":"FMA",
"22-10":"A/P and F/D",
"22-30":"Autothrust",
"22-83":"FMGC"]
]
First level string pair is the chapter number and title, second level is each chapters code and its associated aircraft system. The dictionary will be quite long (this is just a few rows from it) but the format is the same so I don’t see a reason for a struct
, given its simple construction.
Now, I will have a known exact system code – something like "21-52-30A"
and with that String I need to find and return:
-
the chapter name, e.g. “Air Conditioning” (value) from the top level value because the first 2 characters are 21, and
-
the system name, e.g. “Air cooling system” (value) from the second level because the first 4 characters are “21-52”.
In other words, how do I match the key from the top level to the first 2 characters in my known string, and the key from the second level to the first 4 characters, and return their respective values?
I’ve done this so far:
for (keys, values) in ataChapter {
for (item) in keys {
print(item.value)
}
for (chapter) in values {
print(chapter.value)
}
}
I understand the concept of this simple loop, and with it I obviously get all the string values back but I’m a beginner at this stuff and can’t figure out the matching part and return only the values matching the code in my String.
5
If you insist on keeping your dictionary structure here is one way to do it
let chapterKey = "21"
let sectionKey = "21-52"
if let chapter = ataChapter.first(where: { $0.key[chapterKey] != nil }),
let section = chapter.value.first(where: { $0.key == sectionKey }) {
print(chapter.key.values.first!)
print(section.key, section.value)
}
Air Conditioning
21-52 Air cooling system
If you don’t like the forced unwrapping you could include
let chapterTitle = chapter.key.values.first,
in the if condition and use that variable instead.
Another solution is to use custom types instead of the dictionary construction. For example
struct Section {
let key: String
let title: String
}
struct Chapter {
let key: String
let title: String
let sections: [Section]
}
and then have an array of Chapter. The search code would be pretty similar to what we already have but the advantage of a custom structure is that we can add functionality to it so for instance implement a subscript
in Chapter:
subscript(_ sectionKey: String) -> Section? {
sections.first(where: { $0.key == sectionKey })
}
If we also use a dictionary instead of an array with the chapter key as key
let chapters: [String: Chapter] = ...
then the search code could be simplified to
if let chapter = chapters[chapterKey], let section = chapter[sectionKey] {
print(chapter.title)
print(section.key, section.title)
}
1