Remove item that is inside of an array which is th

2020-04-21 04:12发布

问题:

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 = [String:[String]]()

What I want to do is to remove a certain index inside of the array (the dictionary's value). Say I want to remove the string "Chair" from this code:

dict = ["Furniture": ["Table", "Chair", "Bed"], "Food": ["Pancakes"]]

Sorry again if this has already been answered.

回答1:

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"]]          */


回答2:

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"]]


回答3:

guard var furniture = dict["Furniture"] else {
    //oh shit, there was no "Furniture" key
}
furniture.removeAtIndex(1)
dict["Furniture"] = furniture


标签: swift2 xcode7