One can filter an array like this in swift:
var numbers = Array(1...1000000)
numbers = numbers.filter( { return $0 % 2 == 0 } )
Is it possible to filter and avoid the copy operation, that occurs when the filtering is done, eg mutating the original array.
In a similar way to this pseudocode: numbers.MutablefilterOperation({ return $0 % 2 == 0})
In C++ the equvivalent to what is going on in Swift above would be:
std::vector<int> originalNumbers(1000000);
std::vector<int> newNumbers;
std::copy_if (originalNumbers.begin(), originalNumbers.end(), std::back_inserter(newNumbers), [](int i) { return i % 2 == 0 } );
What I would like to achieve for performance reasons:
std::vector<int> originalNumbers(1000000);
auto pos = std::remove_if(originalNumbers.begin(), originalNumbers.end(), [](int x) { return x % 2 == 0; });
originalNumbers.erase(pos, originalNumbers.end());
This implementation should do the filtering without having to make a temporary copy of the entire array in the process (unless a copy of it is referenced by another variable, see "Copy on Write")
extension Array {
mutating func filterInPlace(isIncluded: (Element) throws -> Bool) rethrows {
var writeIndex = self.startIndex
for readIndex in self.indices {
let element = self[readIndex]
let include = try isIncluded(element)
if include {
if writeIndex != readIndex {
self[writeIndex] = element
}
writeIndex = self.index(after: writeIndex)
}
}
self.removeLast(self.distance(from: writeIndex, to: self.endIndex))
}
}
// example:
var arr = [6,2,6,5,2,5,6,2,2,1,6,7,3]
arr.filterInPlace { $0 % 2 == 1 }
print(arr) // [5, 5, 1, 7, 3]
Any Array
is a struct
which is a value type. It can't be mutated, only copied or replaced.
Structures and Enumerations Are Value Types
If you want a reference type you'll have to use a class
to implement your own type of array which is mutable - or use Foundation's NSMutableArray
.
If you want to simplify the code so you can call it as a mutating function you could do it with an extension
:
extension Array {
// the mutating function should be named "filter" but
// this is already taken by the non-mutating function
mutating func filtering(_ isIncluded: (Element) throws -> Bool) rethrows -> [Element] {
try self = self.filter(isIncluded)
return self
}
}
var numbers = Array(1...10)
numbers.filtering( { return $0 % 2 == 0 } )
print(numbers) // "[2, 4, 6, 8, 10]\n"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.