3

Convert [String:Any] dictionary array to [String:String] in Swift

I have an array of dictionary <String,Any> type. Now I want to convert to string because I want to show data in textField and text field not understand Any data type.

My data like this:

var myarr = [[String:Any]]()

[
    [
        "Area" : "",
        "Good" : "-",
        "Level" : 2,
        "Link" : "<null>",
        "Photo" : "-",
        "Repair" : "-",
        "Section" : "Others"
    ],

    [
        "Area" : "",
        "Good" : "N",
        "Level" : 2,
        "Link" : "http://google.com",
        "Photo" : 1,
        "Repair" : "Y",
        "Section" : "Grounds"
    ]

]

and I want new Array Dictionary:

var myarr = [[String:String]]()
Harshil Kotecha
  • 2,846
  • 4
  • 27
  • 41

3 Answers3

7

Map is your friend, maybe something like

let stringDictionaries: [[String: String]] = myarr.map { dictionary in
    var dict: [String: String] = [:]
    dictionary.forEach { (key, value) in dict[key] = "\(value)" }
    return dict
}
John Dough
  • 285
  • 1
  • 7
  • thank you it's work properly and not get any error in type converting – Harshil Kotecha May 02 '17 at 05:30
  • 2
    This answer is wrong. It adds an extra layer of arrays to the results. – rmaddy May 02 '17 at 05:30
  • please give another solution @rmaddy i am waiting for your solution – Harshil Kotecha May 02 '17 at 05:31
  • @HarshilKotecha I updated the example using flatMap to flatten the structure to match your desired output. :) – John Dough May 02 '17 at 05:33
  • 2
    The update is wrong too. `flatmap` doesn't change anything here. Please verify your answer before posting. A simple test in the playground should be done. – rmaddy May 02 '17 at 05:34
  • @rmaddy I'm actually testing this in Playgrounds and the output gives me `[["test1": "123"], ["test2": "345"], ["test3": "657"], ["test4": "true"]]` just like OP is looking for. What do you see in Playgrounds? – John Dough May 02 '17 at 05:36
  • 2
    Your test isn't valid. Test with a dictionary that has more than one key/value pair just like the data in the question. – rmaddy May 02 '17 at 05:37
  • Print the original array and your result array. Note how the result has a bunch of extra dictionaries. – rmaddy May 02 '17 at 05:45
  • @HarshilKotecha Not at all. It has nothing to do with memory. The result is creating a dictionary for each key/value pair found in the original dictionaries. – rmaddy May 02 '17 at 05:48
  • @JohnDough check your out put and than my code [["Section": "Grounds"]] it is true ? – Harshil Kotecha May 02 '17 at 05:51
  • let dict = stringDictionaries[0] print(dict["Section"]) check this it's not work in your output result – Harshil Kotecha May 02 '17 at 05:56
  • @rmaddy thanks for staying alert - updated the example to not split into sub-dictionaries. Cheers! – John Dough May 02 '17 at 06:14
  • Yep, that works. You can't use `map` on a dictionary to get a new dictionary. – rmaddy May 02 '17 at 06:17
5

Here is one solution that actually gives the correct results:

let myarr = [
    [
        "Area" : "",
        "Good" : "-",
        "Level" : 2,
        "Link" : "<null>",
        "Photo" : "-",
        "Repair" : "-",
        "Section" : "Others"
    ],

    [
        "Area" : "",
        "Good" : "N",
        "Level" : 2,
        "Link" : "http://someurl",
        "Photo" : 1,
        "Repair" : "Y",
        "Section" : "Grounds"
    ]
]


var newarr = [[String:String]]()
for dict in myarr {
    var newdict = [String:String]()
    for (key, value) in dict {
        newdict[key] = "\(value)"
    }
    newarr.append(newdict)
}
print(newarr)

Output:

[["Level": "2", "Area": "", "Good": "-", "Link": "<null>", "Repair": "-", "Photo": "-", "Section": "Others"], ["Level": "2", "Area": "", "Good": "N", "Link": "http://someurl", "Repair": "Y", "Photo": "1", "Section": "Grounds"]]

rmaddy
  • 314,917
  • 42
  • 532
  • 579
1

You can create new dictionary using following code:

var newArray:[[String: String]] = []
for data in myarr {
    var dict: [String: String] = [:]
    for (key, value) in data {
        let strData = String(describing: value)
        dict[key] = strData
    }
    newArray.append(dict)
}