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.
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)
}