I know this might have been answered before, but I couldn\'t find anything when i searched.
So i have a dictionary that looks like this:
var dict = [Stri
guard var furniture = dict["Furniture"] else {
//oh shit, there was no "Furniture" key
}
furniture.removeAtIndex(1)
dict["Furniture"] = furniture
Many answers that cover the mutation of dictionary entries tend to focus on the remove value -> mutate value -> replace value idiom, but note that removal is not a necessity. You can likewise perform an in-place mutation using e.g. optional chaining
dict["Furniture"]?.removeAtIndex(1)
print(dict)
/* ["Furniture": ["Table", "Bed"],
"Food": ["Pancakes"]] */
Note however that using the .removeAtIndex(...)
solution is not entirely safe, unless you perform an array bounds check, making sure that the index for which we attempt to remove an element actually exists.
As a safe in-place-mutation alternative, use the where
clause of an optional binding statement to check the the index we want to remove is not out of bounds
let removeElementAtIndex = 1
if let idxs = dict["Furniture"]?.indices where removeElementAtIndex < idxs.endIndex {
dict["Furniture"]?.removeAtIndex(removeElementAtIndex)
}
Another safe alternative is making use of advancedBy(_:limit)
to get a safe index to use in removeAtIndex(...)
.
let removeElementAtIndex = 1
if let idxs = dict["Furniture"]?.indices {
dict["Furniture"]?.removeAtIndex(
idxs.startIndex.advancedBy(removeElementAtIndex, limit: idxs.endIndex))
}
Finally, if using the remove/mutate/replace idiom, another safe alternative is using a flatMap
for the mutating step, removing an element for a given index, if that index exists in the array. E.g., for a generic approach (and where
clause abuse :)
func removeSubArrayElementInDict<T: Hashable, U>(inout dict: [T:[U]], forKey: T, atIndex: Int) {
guard let value: [U] = dict[forKey] where
{ () -> Bool in dict[forKey] = value
.enumerate().flatMap{ $0 != atIndex ? $1 : nil }
return true }()
else { print("Invalid key"); return }
}
/* Example usage */
var dict = [String:[String]]()
dict = ["Furniture": ["Table", "Chair", "Bed"], "Food": ["Pancakes"]]
removeSubArrayElementInDict(&dict, forKey: "Furniture", atIndex: 1)
print(dict)
/* ["Furniture": ["Table", "Bed"],
"Food": ["Pancakes"]] */
If you want to remove specific element, you could do this:
var dict = ["Furniture": ["Table", "Chair", "Bed"], "Food": ["Pancakes"]]
extension Array where Element: Equatable {
mutating func removeElement(element: Element) {
if let index = indexOf ({ $0 == element }) {
removeAtIndex(index)
}
}
}
dict["Furniture"]?.removeElement("Chair") //["Furniture": ["Table", "Bed"], "Food": ["Pancakes"]]