> On 19 Jun 2016, at 05:58, Saagar Jha via swift-evolution 
> <[email protected]> wrote:
> 
> This isn’t actually that complex, especially if you ditch the “C-style” for 
> loop algorithm and switch it to, as you mentioned, “filtering code”. filter, 
> enumerated (to get indices), and map (to go back to elements) are more than 
> up to the task. Plus, this is much more efficient.
> 
> var myArray = [0, 1, 2]
> let indices: Set = [0, 1]
> myArray = myArray.enumerated().filter {
>     return !indices.contains($0.offset)
> }.map {
>     return $0.element // to get the elements back
> }
> print(myArray) // prints “[2]"
> Adding it to the standard library might be useful, but it’s not as hard as it 
> looks.
> 

Has .enumerated() been changed to use the collection’s internal Index type? 
Last time I tried something like this it failed because .enumerated() only 
returns numeric offsets, but the index type of a collection may not necessary 
be compatible (not all indices are just a plain numeric value, consider a type 
that returns AnyIndex). So this will only work when your indices are integers 
starting from zero.

I think the following should work for the generic case, and is pretty similar:

extension MutableCollection {
        public mutating func remove(indices: Set<Index>) {
                var index = self.startIndex
                self = self.filter {
                        let result = indices.contains(index)
                        self.formIndex(after: &index)
                        return result
                }
        }
}

(note: I'm not in a position to test this just now so it may not work exactly 
as written, but that’s the gist of how to do it safely I think)

The main question I have is how do you get into a situation where you’ve 
generated the indices, but could not put the same code into a call to .filter? 
For example:

        var indicesToRemove:Set<Index> = []
        for eachIndex in myArray.indices {
                if someCondition(myArray[eachIndex]) { 
indicesToRemove.insert(eachIndex) }
        }
        myArray.remove(indices: indicesToRemove)

Could be rewritten as:

        myArray = myArray.filter { someCondition($0) }

If what we want is in-place removal then I think what we need is some kind of 
MutatingIteratorProtocol which includes a .remove() method; this method would 
remove the last element retrieved without invalidating the iterator or skipping 
an element, allowing us to do the following:

        var iterator = myArray.makeIterator() // Conforms to 
MutatingIteratorProtocol
        while let eachElement = iterator.next() {
                if someCondition(eachElement) { iterator.remove() }
        }
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to