> 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