Array as a dictionary value in swift language
Note that subscript
returns an optional. We have to force unwrapping:
println(list[2543]![0])
Or use optional chaining
println(list[2543]?[0])
Swift - Adding value to an array inside a dictionary
EDIT: Thanks to Martin's comment. The snippet below is the the most succinct answer I can think of. I was initially coming at it from a wrong direction. and I was getting an error. See comments
struct Student {
let id: Int
let subject : String
}
var studentArray = [Student(id: 1, subject: "History"), Student(id: 2, subject: "History"), Student(id:1, subject: "Maths")]
typealias Subject = String
var dict : [Int: [Subject]] = [:]
for student in studentArray {
(dict[student.id, default: []]).append(student.subject)
}
print(dict)
Previous answers:
struct Student {
let id: Int
let subject : String
}
var studentArray = [Student(id: 1, subject: "History"), Student(id: 2, subject: "History"), Student(id:1, subject: "Maths")]
typealias Subject = String
var dict : [Int: [Subject]] = [:]
for student in studentArray {
var subjects = dict[student.id] ?? [String]()
subjects.append(student.subject)
dict[student.id] = subjects
}
print(dict)
Or you can do it this way:
struct Student {
let id: Int
let subject : String
}
var studentArray = [Student(id: 1, subject: "History"), Student(id: 2, subject: "History"), Student(id:1, subject: "Maths")]
typealias Subject = String
var dict : [Int: [Subject]] = [:]
for student in studentArray {
if let _ = dict[student.id]{
dict[student.id]!.append(student.subject)
}else{
dict[student.id] = [student.subject]
}
}
print(dict)
whichever you like
How to initialize an array inside a dictionary?
I think you could be misunderstanding something pretty key - let's make sure:
The way the dictionary works, is not to have one array, but an array for each key.
Each value of 'idx' you request the array for returns a different array.
You can't expect it to return an empty array - a dictionary is meant to return a nil value for a key that hasn't been set. To do what you're trying, the following would probably do the trick:
myDict[idx] = myDict[idx] ?? []
Swift: Filter a Dictionary with Array as Value
Here's a solution that maps the values based on the search and then filters out the empty results.
var dictionary = ["a": ["aberration", "abc"], "b" : ["babel", "bereft"]]
var searchText = "aberration"
let filteredDictionary = dictionary.mapValues { $0.filter { $0.hasPrefix(searchText) } }.filter { !$0.value.isEmpty }
print(filteredDictionary)
Output:
["a": ["aberration"]]
Swift 3: Array to Dictionary?
I think you're looking for something like this:
extension Array {
public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] {
var dict = [Key:Element]()
for element in self {
dict[selectKey(element)] = element
}
return dict
}
}
You can now do:
struct Person {
var name: String
var surname: String
var identifier: String
}
let arr = [Person(name: "John", surname: "Doe", identifier: "JOD"),
Person(name: "Jane", surname: "Doe", identifier: "JAD")]
let dict = arr.toDictionary { $0.identifier }
print(dict) // Result: ["JAD": Person(name: "Jane", surname: "Doe", identifier: "JAD"), "JOD": Person(name: "John", surname: "Doe", identifier: "JOD")]
If you'd like your code to be more general, you could even add this extension on Sequence
instead of Array
:
extension Sequence {
public func toDictionary<Key: Hashable>(with selectKey: (Iterator.Element) -> Key) -> [Key:Iterator.Element] {
var dict: [Key:Iterator.Element] = [:]
for element in self {
dict[selectKey(element)] = element
}
return dict
}
}
Do note, that this causes the Sequence to be iterated over and could have side effects in some cases.
Retrieve first dictionary value swift
This should do the trick:
It's a good initiative when learning programming to use manual for loop instead of magical methods like map()
, etc, in an algorithmic way. They do loop, but they are implicit.
Here, I used the sorted()
(because else it can be a little long).
I also used first(where:)
, it finds the first non-empty value. It also can be replaced with a while loop, but I didn't know if you wanted a for loop to.
var dict = [1: ["Value-1-1", "", ""],
2: ["", "Value-2-2", "Value-2-3"],
3: ["Value-3-1", "Value-3-2", ""],
4: ["Value-4-1", "", "Value-4-3"],
5: ["", "", "Value-5-3"]]
var finalArray = [String]()
let keys = Array(dict.keys).sorted(by: { return $0<$1 }) // because keys aren't sorted
for aKey in keys {
if let anArrayValue = dict[aKey], let firstNonEmptyValue = anArrayValue.first(where: { !$0.isEmpty }) {
finalArray.append(firstNonEmptyValue)
}
}
print("finalArray: \(finalArray)")
See @Martin R answer for the version with "higher level" methods, but more complicated to understand for debutants (chaining, closures, etc.). It does the same, just more compact, less explicit.
How to Mutate an Array in a Dictionary?
In swift, structures are copied by value when they get assigned to a new variable. So, when you assign a1
to the value in the dictionary it actually creates a copy. Here's the line I'm talking about:
var a1 = d1["a"]!
Once that line gets called, there are actually two lists: the list referred to by d1["a"]
and the list referred to by a1
. So, only the second list gets modified when you call the following line:
a1.append("s1")
When you do a print, you're printing the first list (stored as the key "a"
in dictionary d1
). Here are two solutions that you could use to get the expected result.
Option1: Append directly to the array inside d1
.
var d1 = [String : [String]]()
d1["a"] = [String]()
d1["a"]?.append("s1")
println(d1)
Option 2: Append to a copied array and assign that value to "a"
in d1
.
var d1 = [String : [String]]()
d1["a"] = [String]()
var a1 = d1["a"]!
a1.append("s1")
d1["a"] = a1
println(d1)
The first solution is more performant, since it doesn't create a temporary copy of the list.
Swift language: How do I implement a dictionary of array values, and assign (ie. append) new values to the array?
var unloadedRows = imagesRowForLocation(forLocation)
unloadedRows!.append(row)
unloadedImagesRows[forLocation] = unloadedRows!
You retrieve the array by value, i.e. another instance of the array stored inside the dictionary gets created. Therefore you should set it back into the dictionary after appending a value
Appending dictionary values to array in Swift
You should only sort the keys and then use that array to select from the dictionary and append your sortedValues
array. I made the sortedKeys
into a local variable
func sortItems() {
let sortedKeys = self.dictionary.keys.sorted(by: >)
for key in sortedKeys {
if let obj = dictionary[key] {
self.sortedValues.append(obj)
}
}
}
I don't know if this will make a difference in regard to the crash but another way is to let the function return an array
func sortItems() -> [Object] {
let sortedKeys = self.dictionary.keys.sorted(by: >)
var result: [Object]()
for key in sortedKeys {
if let obj = dictionary[key] {
result.append(obj)
}
}
return result
}
and then call it
self.sortedValues = sortItems()
Related Topics
Swiftui - in Sheet Have a Fixed Continue Button That Is Not Scrollable
How to Speed Up Updating Relationship Among Tables, After One or Both Tables Are Already Saved
Array as a Dictionary Value in Swift Language
How to Delete an Item in a Collection View with a Button in the Cell
A Switch Bug in Swift? - "Switch Must Be Exhaustive, Consider Adding a Default Clause."
Issue with Adding Node to Scene View
How to Share Data Between Tab View Controllers
Animate Cell When Pressed Using Swift 3
Does Swift Compile to Native Code
Swift Add Badge to Navigation Barbuttonitem and Uibutton
Add Skreferencenode/Skscene to Another Skscene in Spritekit
How Are Int and String Accepted as Anyhashable
My Uiviewcontroller Is Not Filling the Entire Screen
Uibarbuttonitem Selector Not Working
Nsjsonserialization Not Working as Expected in a Playground
How to Make My Level Menu Scrollable Vertically
How to Access a Swift Enum Associated Value Outside of a Switch Statement