I am really not getting this - why is this not working?
var listOfFruit = ["Apple", "Banana","Lemon"]
var emptyDict = [String: String]()
var key = ["Name of Fruit","Name of Fruit","Name of Fruit"]
func createDictionary(){
var index: Int
index = listOfFruit.count
for index in listOfFruit {
emptyDict = [key[index]:listOfFruit[index]]
print (emptyDict)
}
}
I am getting the usual :
I'm trying to guess what you need because your question is pretty unclear.
IF given this input
var fruits = ["Apple", "Banana","Lemon"]
var keys = ["Name of Fruit", "Name of Fruit", "Name of Fruit"]
you want this output
["Name of Fruit 2": "Lemon", "Name of Fruit 0": "Apple", "Name of Fruit 1": "Banana"]
Then you can use this code
let dict = zip(fruits, keys).enumerate().reduce([String:String]()) { (var result, elm) -> [String:String] in
let key = "\(elm.element.1) \(elm.index)"
let value = elm.element.0
result[key] = value
return result
}
or this code
assert(keys.count == fruits.count)
var dict = [String:String]()
for i in 0..<fruits.count {
let key = "\(keys[i]) \(i)"
let value = fruits[i]
dict[key] = value
}
Related
I have a dictionary with two Int’s A:B, and I want create a new dictionary that includes B as an index (with no repetition) and A as a value (only for repeated B’s):
var myDict : [Int:Int] = [12:2345, 14:2345, 99:1111, 67:1111, 77:7657, 132:3345, 199:6778]
Desired output:
var newDict: [Int:[Int]] = [2345: [ 12 , 14 ] , 1111: [ 99 , 67] ]
Note: the original dictionary contains over a thousand entries.
You loop through the first dict by enumerating it, that way you can switch the values in to the new dict
var newDict: [Int:[Int]] = [:]
let myDict : [Int:Int] = [12:2345, 14:2345, 99:1111, 67:1111, 77:7657, 132:3345, 199:6778]
for values in myDict.enumerated() {
var newValue = newDict[values.element.value] ?? []
newValue.append(values.element.key)
newDict[values.element.value] = newValue
}
newDict = newDict.filter { (key, value) -> Bool in
value.count > 1
}
Here is the power of swift:
let newDict = Dictionary(grouping: myDict, by: {$0.value}).filter({$0.value.count > 1}).mapValues({$0.map({$0.key})})
print(newDict)
Output: [1111: [67, 99], 2345: [12, 14]]
Please use this code:
var myDict: [Int:Int] = [12:2345, 14:2345, 99:1111, 67:1111, 77:7657, 132:3345, 199:6778]
let values = myDict.values
let tempValueSet = Set<Int>(values)
let uniqueValues = Array(tempValueSet)
var result = [Int: [Int]]()
for item in uniqueValues {
result[item] = myDict.allKeys(forValue: item)
}
print(result)
And this is Dictionary extension:
extension Dictionary where Value: Equatable {
func allKeys(forValue val: Value) -> [Key] {
return self.filter { $1 == val }.map { $0.0 }
}
}
Desired output:
[6778: [199], 1111: [99, 67], 7657: [77], 3345: [132], 2345: [12, 14]]
For more reference about this extension : https://stackoverflow.com/a/27218964/2284065
If you don't want to use extension then you can use this code too :
var myDict: [Int:Int] = [12:2345, 14:2345, 99:1111, 67:1111, 77:7657, 132:3345, 199:6778]
let values = myDict.values
let tempValueSet = Set<Int>(values)
let uniqueValues = Array(tempValueSet)
var result = [Int: [Int]]()
for item in uniqueValues {
result[item] = (myDict as NSDictionary).allKeys(for: item) as! [Int]
}
print(result)
let arra = ["abc","def","abc","def"]
let arra2 = ["addr1","addr2","addr1","addr2"]
Expected Output
dic = ["abc":"addr1","addr1" , def: "addr2","addr2"]
Swift 4's new Dictionary initializer lets you do that kind of thing easily:
let arra = ["abc","def","abc","def"]
let arra2 = ["addr1","addr2","addr1","addr2"]
let dict = [String:[String]](zip(arra,arra2.map{[$0]}),uniquingKeysWith:+)
print(dict) // ["abc": ["addr1", "addr1"], "def": ["addr2", "addr2"]]
[EDIT] Swift 3 equivalent :
var dict : [String:[String]] = [:]
zip(arra,arra2.map{[$0]}).forEach{ dict[$0] = (dict[$0] ?? []) + $1 }
There should be easier way but in general:
import UIKit
let keyArray = ["abc","def","abc","def"]
let valueArray = ["addr1","addr2","addr1","addr2"]
let setFromKeyArray = Set(keyArray)
var finalDict = [String: [String]]()
for index in 0..<keyArray.count {
if let _ = finalDict[keyArray[index]] {
finalDict[keyArray[index]]!.append(valueArray[index])
} else {
finalDict[keyArray[index]] = [valueArray[index]]
}
}
print(finalDict)
// output: ["abc": ["addr1", "addr1"], "def": ["addr2", "addr2"]]
Using zip(_:_:) and reduce(_:_:):
let array1 = ["abc", "def", "abc", "def"]
let array2 = ["addr1", "addr2", "addr1", "addr2"]
let dictionary = zip(array1, array2).reduce([String: String]()) {
var dictionary = $0
dictionary[$1.0] = $1.1
return dictionary
}
print(dictionary) // ["abc": "addr1", "def": "addr2"]
You can use like below :
let arra = ["abc","def","abc","def"]
let arra2 = ["addr1","addr2","addr1","addr2"]
var dictionary: [String: String] = [:]
dictionary.merge(zip(arra, arra2)) { (old, new) -> String in
return "\(old), \(new)"
}
print(dictionary)
Output :
["abc": "addr1, addr1", "def": "addr2, addr2"]
The best of Dennis and Kristijan and Alain.
let arra = ["abc", "def", "abc", "def"]
let arra2 = ["addr1", "addr2", "addr1", "addr2"]
let dict = zip(arra, arra2).reduce([String:[String]]()){
var d = $0
d[$1.0] = ($0[$1.0] ?? []) + [$1.1]
return d
}
print(dict) // ["def": ["addr2", "addr2"], "abc": ["addr1", "addr1"]]
Remember dictionary is unordered.
I have a dictionary that looks like this:
var dict = [String: [String]]()
I want to be able to add multiple arrays for a single key. This works fine:
dict["hello"] = ["item 1"]
But when I assign a new array the previous value is obviously overwritten - we want to avoid that:
dict["hello"] = ["item 2"] // overwrites item 1 – how to avoid overwriting?
So I tried to use the append method, but this returns nil:
dict["hello"]?.append("test") // does nothing? output: ()
How can I append strings to the array (value) of a certain key in Swift?
First of all...
... you don't really want this
I want to be able to add multiple arrays for a single key.
Instead I think you want...
... to add a string to the array associated to a given string
Example
In other words you want to go from this
["hello":["item 1"]]
to this
["hello":["item 1", "item 2"]]]
So, how to do it?
Let's begin with your dictionary
var dict = [String: [String]]()
dict["hello"] = ["item 1"]
Now you need to extract the array associated to the hello key
var list = dict["hello"] ?? []
adding a string to it
list.append("item 2")
and finally adding the updated array back into the dictionary
dict["hello"] = list
That's it
This is what your code does
dict["hello"] = ["item 1"] - This sets hello to ["item 1"]
dict["hello"] = ["item 2"] - This sets hello to ["item 2"]
This is just like a variable, for example:
var hello = Array<String>()
hello = ["item 1"] // prints out ["item 1"]
hello = ["item 2"] // prints out ["item 2"]
This is what is happening with your dictionary. You are overriding any stored data with new data.
The problem with appending. This only works if there is already an array at that key.
dict["hello"]?.append("test") This wouldn't work.
But this would.
dict["hello"] = ["test 1"]
dict["hello"]?.append("test")
print(dict) // prints out ["dict":["test 1","test"]]
What you need to do
var dict = Dictionary<String,Array<String>>()
func add(string:String,key:String) {
if var value = dict[key] {
// if an array exist, append to it
value.append(string)
dict[key] = value
} else {
// create a new array since there is nothing here
dict[key] = [string]
}
}
add(string: "test1", key: "hello")
add(string: "test2", key: "hello")
add(string: "test3", key: "hello")
print(dict) // ["hello": ["test1", "test2", "test3"]]
Dictionary Extension
extension Dictionary where Key == String, Value == Array<String> {
mutating func append(_ string:String, key:String) {
if var value = self[key] {
// if an array exist, append to it
value.append(string)
self[key] = value
} else {
// create a new array since there is nothing here
self[key] = [string]
}
}
}
How to use
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
var dict = Dictionary<String,Array<String>>()
dict.append("first", key: "hello")
dict.append("second", key: "hello")
dict.append("thrid", key: "hello")
dict.append("one", key: "goodbye")
dict.append("two", key: "goodbye")
print(dict) // ["hello": ["first", "second", "thrid"], "goodbye": ["one", "two"]]
}
Please try this thing and let me know if this is what you require
import UIKit
var dict = [String: [String]]()
if var value = dict["hello"]{
value.append("Hi")
dict["hello"] = value
}else{
dict["hello"] = ["item 1"]
}
Other people have the correct solution. Here is a quick shorthand for the same answer.
var dict = [String: [String]]()
dict["hello"] = (dict["hello"] ?? []) + ["item 1"]
dict["hello"] = (dict["hello"] ?? []) + ["item 2"]
In Swift 4, this will be
var dict = [String: [String]]()
dict["hello"] = dict["hello", default: []] + ["item 1"]
dict["hello"] = dict["hello", default: []] + ["item 2"]
In the Playground example below I'm trying to modify a multidimensional NSMutableDictionary. Can someone please explain the correct way to modify a multidimensional mutable dictionary?
import Cocoa
let player = "Player 1"
let characterName = "Magic Glop"
let strength = 23
let defense = 220
let type = "fire"
var example: NSMutableDictionary = ["id":1,
"player":player,
"characters":
["character-name":characterName,
"stats":
["strength":strength,
"defense":defense,
"type":type
]
]
]
// My first attempt to update character-name.
example["characters"]!["character-name"] = "New Name"
// Error: Cannot assign to immutable expression of type 'AnyObject?!'
// Next I tried updating the value of "characters">"stats">"type" with .setObject
example["characters"]!["stats"]!!.setObject("water", forKey: "type")
// Documentation: .setObject adds a given key-value pair to the dictionary. If the key already exists in the dictionary, the object takes its place.
// Error: Execution was interrupted, reason: EXC_BAD INSTRUCTION (code=EXC_i386_INVOP, suncode=0x0).
Thanks in advance!
Class approach: You can update var to let for non-editable parameters.
class Player {
let id: Int
var name: String
var characters = [Character]()
init(id: Int, name: String) {
self.id = id
self.name = name
}
/**
Add new char to Player
*/
func addNewCharacter(new: Character) {
self.characters.append(new)
}
}
class Character {
var name: String
var strength: Int
var defense: Int
var type: String
init(name: String, strength: Int, defense: Int, type: String) {
self.name = name
self.strength = strength
self.defense = defense
self.type = type
}
}
func createPlayer() {
let player1 = Player(id: 1, name: "Bodrum")
// create new char and add to the player1 named Bodrum
let char1 = Character(name: "Magic Glop", strength: 23, defense: 220, type: "fire")
player1.addNewCharacter(char1)
print("old name:\(player1.characters[0].name), old type:\(player1.characters[0].type)")
// update char1's parameters
player1.characters[0].name = "Yalikavak"
player1.characters[0].type = "water"
print("new name:\(player1.characters[0].name), new type:\(player1.characters[0].type)")
}
// old name:Magic Glop, old type:fire
// new name:Yalikavak, new type:water
check this answer.
let player = "Player 1"
let characterName = "Magic Glop"
let strength = 23
let defense = 220
let type = "fire"
var example: [String: AnyObject] = ["id":1,
"player":player,
"characters":
["character-name":characterName,
"stats":
["strength":strength,
"defense":defense,
"type":type
]
]
]
print(example)
var charDic = example["characters"] as! [String: AnyObject]
charDic["character-name"] = "New Name" // change value for key character-name
var statsDic = charDic["stats"] as! [String: AnyObject]
statsDic["type"] = "water" // change the value for type
charDic["stats"] = statsDic // assign updated dic for key stats
example["characters"] = charDic // assign updated dic for key chacracters
print(example)
I want to fill the dictionary with data, so that it looks like this:
1:Apple
2:Banana
3:Lemon
Sorry, if this is too simple for probably most of you - I am just a beginner. Anyway, here is the code:
var listOfFruit = ["Apple", "Banana","Lemon"]
var key = [1,2,3]
var dictionary = [Int: [String]]()
func createDictionary(){
for index in key {
dictionary[index] = []
var listOfFruit = ["Apple", "Banana","Lemon"]
for index1 in listOfFruit{
dictionary[index]?.append(index1)
}
}
}
print(dictionary)
The result of the above is "[:]\n" in my playground.
A functional approach to creating your dictionary could look like this:
let dictionary = zip(listOfFruit, key).map { [$1: $0] }
print(dictionary)
// [[1: "Apple"], [2: "Banana"], [3: "Lemon"]]
let listOfFruit = ["Apple", "Banana","Lemon"]
let key = [1,2,3]
var dictionary = [Int: String]()
func createDictionary(){
var i = 0
while i < listOfFruit.count {
dictionary[key[i]] = listOfFruit[i]
i += 1
}
}
createDictionary()
print(dictionary)
Note the change of the line:
var dictionary = [Int: [String]]()
to:
var dictionary = [Int: String]()
and the use of the variable i to get the same index from each array.
var listOfFruit = ["Apple", "Banana","Lemon"]
var key = [1,2,3]
var dictionary = [Int: String]()
func createDictionary(){
for (index, value) in key.enumerate() {
dictionary[value] = listOfFruit[index]
}
}
createDictionary()
print(dictionary)