In Swift I want to make an array of dictionaries (with multiple key value pairs) and then iterate over each element
Below is the expected output of a possible dictionary. Not sure how to declare and intitialize it (somewhat similar to array of hashes in Ruby)
dictionary = [{id: 1, name: "Apple", category: "Fruit"}, {id: 2, name: "Bee", category: "Insect"}]
I know how to make an array of dictionary with one key value pair.
For example:
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
to declare an array of dictionary, use this:
var arrayOfDictionary: [[String : AnyObject]] = [["id" :1, "name": "Apple", "category" : "Fruit"],["id" :2, "name": "Microsoft", "category" : "Juice"]]
I see that in your dictionary, you mix number with string, so it's better use AnyObject instead of String for data type in dictionary.
If after this code, you do not have to modify the content of this array, declare it as 'let', otherwise, use 'var'
Update: to initialize within a loop:
//create empty array
var emptyArrayOfDictionary = [[String : AnyObject]]()
for x in 2...3 { //... mean the loop includes last value => x = 2,3
//add new dictionary for each loop
emptyArrayOfDictionary.append(["number" : x , "square" : x*x ])
}
//your new array must contain: [["number": 2, "square": 4], ["number": 3, "square": 9]]
let dic_1: [String: Int] = ["one": 1, "two": 2]
let dic_2: [String: Int] = ["a": 1, "b": 2]
let list_1 = [dic_1, dic_2]
// or in one step:
let list_2: [[String: Int]] = [["one": 1, "two": 2], ["a": 1, "b": 2]]
for d in list_1 { // or list_2
print(d)
}
which results in
["one": 1, "two": 2]
["b": 2, "a": 1]
let airports: [[String: String]] = [["YYZ": "Toronto Pearson", "DUB": "Dublin"]]
for airport in airports {
print(airport["YYZ"])
}
Related
I have an array of dictionaries, like this
myDicArray = [[
"id": "105",
"b": "apple",
"c": "red",
],
[
"id": "409",
"b": "pear",
"c": "yellow",
],
[
"id": "769",
"b": "orange",
"c": "orange",
]]
I was wondering is there a way to do a binary search based on the value of "id", and retrieve the corresponding dictionary?
For example, if I take input 409, can I do a binary search on [105, 409, 769] and the output should be;
[
"id": "409",
"b": "pear",
"c": "yellow",
]
I found a method from GitHub to implement binary search on an array;
func binarySearch<T: Comparable>(_ a: [T], key: T) -> Int? {
var lowerBound = 0
var upperBound = a.count
while lowerBound < upperBound {
let midIndex = lowerBound + (upperBound - lowerBound) / 2
if a[midIndex] == key {
return midIndex
} else if a[midIndex] < key {
lowerBound = midIndex + 1
} else {
upperBound = midIndex
}
}
return nil
}
But I am confused about how to implement it on an array of dictionaries?
Really appreciate any help, many thanks in advance!
I have slightly edited the binarySearch function to allow you to search for a value of type T in an array of type [U], provided a function that maps (U) -> T:
func binarySearch<T: Comparable, U>(_ a: [U], key: T, keyMapper: (U) -> T) -> U? {
var lowerBound = 0
var upperBound = a.count
while lowerBound < upperBound {
let midIndex = lowerBound + (upperBound - lowerBound) / 2
if keyMapper(a[midIndex]) == key {
return a[midIndex]
} else if keyMapper(a[midIndex]) < key {
lowerBound = midIndex + 1
} else {
upperBound = midIndex
}
}
return nil
}
Usage:
binarySearch(myDicArray, key: "769") { $0["id"]! }
Note that the IDs in your dictionaries are strings, not numbers, please ensure that they are sorted lexicographically, instead of numerically.
Also, you could consider creating a struct for your data, and using a [MyStruct] to store them instead:
struct MyStruct {
let id: String
let b: String
let c: String
}
let myStructArray = [
MyStruct(id: "105", a: "apple", b: "red"),
...
]
I have an ArraySlice<Dictionary<String, String>> containing only one dictionary inside. This looks like the following:
[["high": "4", "investpercent": "6.0", "objective": "2.0", "savings": "2.0", "expenses": "1.0", "date": "2017-09-26", "low": "2"]]
However I wanted to manipulate the dictionary with subscripts, which is not implemented in ArraySlice. In typical slices one would, as per found question in SO, do something like:
let dictionary = ["a": 1, "b": 2, "c": 3]
var smallerDictionary: [String: Int] = [:]
for (key, value) in dictionary.dropFirst() {
smallerDictionary[key] = value
}
print(smallerDictionary) // ["a": 1, "c": 3]
Which I tried and does not work in ArraySlice.
How do I "unpack" a dictionary from within an ArraySlice?
If your ArraySlice is called slice, use slice.first! or slice[slice.startIndex] to access the contained dictionary:
let slice: ArraySlice<[String:String]> = [["high": "4", "investpercent": "6.0", "objective": "2.0", "savings": "2.0", "expenses": "1.0", "date": "2017-09-26", "low": "2"]]
var smallerDictionary: [String: String] = [:]
for (key, value) in slice.first!.dropFirst() {
smallerDictionary[key] = value
}
print(smallerDictionary)
Note: Calling dropFirst() on a dictionary will give you unpredictable results because dictionaries are unordered.
It should go without saying that you should make sure your ArraySlice isn't empty before attempting to access the contained dictionary. You can do that by explicitly checking slice.count > 0, !slice.isEmpty, or properly unwrapping slice.first.
struct Country {
var translations : [String:String?]? // must be defined as optionals!
}
// example entry
translationsDict = [
"translations": [
"de":"Deutschland",
"en": "germany",
"it": nil
]
]
How can I extract the values "Deutschland" and "germany" into a new array?
result should be:
["germany", "Deutschland"]
Firstly, get a collection of all values of translations, then convert it to an array.
if let collection = translationsDict["translations"]?.values {
let array = Array(collection)
print(array)
}
or
if let array = translationsDict["translations"]?.map({ $0.1 }) {
print(array)
}
My data structure:
var defs = [["a":"b","c":"d"],["e":"f","g":"h"]]
I have tried the following:
dict[1]["testKey"] = "testValue"
in an attempt to attain the following:
defs = [["a":"b","c":"d"],["e":"f","g":"h","testKey":"testValue"]]
This doesn't work though. Does anyone have a good solution?
You have a typo in your code (I see you're using dict instead of defs but this works fine:
var defs = [
[
"a": "b",
"c": "d"
],
[
"e": "f",
"g": "h"
]
]
defs[1]["key"] = "value"
print(defs[1]["key"]) // "Optional("value")\n"
var defs = [["a":"b","c":"d"],["e":"f","g":"h"]]
defs[1]["testKey"] = "testValue"
print(defs)
prints:
[["a": "b", "c": "d"], ["e": "f", "testKey": "testValue", "g": "h"]]
The elements contained within the defs array are of type Dictionary, which by definition is unordered. If the order is an issue, you have to use another collection type.
I created a dictionary in Swift like:
var dict:[String : Int] = ["A": 1, "B": 2, "C": 3, "D": 4]
print(dict["A"]!)
The computer prints number 1, but how do I concatenate these values such that the output is 1234 instead of a single integer?
The key-value pairs in a Dictionary are unordered. If you want to access them in a certain order, you must sort the keys yourself:
let dict = ["A": 1, "B": 2,"C": 3,"D": 4]
let str = dict.keys
.sorted(by: <)
.map { dict[$0]! }
.reduce ("") { $0 + String($1) }
Or alternatively:
let str = dict.keys
.sorted(by: <)
.map { String(dict[$0]!) }
.joined()
No idea about the relative performance of the two as I haven't benchmarked them. But unless your dictionary is huge, the difference will be minimal.
let dict = ["A": 1, "B": 2, "C": 3, "D": 4]
for entry in dict.sorted()
{
print("\(entry.1)", terminator: "")
}