Mutating range of For loops in Swift - arrays

I'm trying to set a dynamic range which changes while iterating inside a for loop. Aka: Jumping from index to index.
For example:
func func(c: [Int]) -> Int {
var currentIndex = 0
for i in currentIndex..<c.count
currentIndex += 3 //After changing the currentIndex value, will my "i" start from currentIndex?
}
So i starts with 0, then it will be 3, then 6 and so on...
When I run this code, "i" sums up as usual like i = 0, i = 1, i = 2... Can I mutate the iteration range?

As in comments, one powerful solution is using build in stride. Another solution is
while currentIndex < c.count
{
//your loop logic
currentIndex += 3
}
you don't need an 'i'.

Related

Swift: Capture list

var array = [() -> ()]()
var count = 0
var index = 0
while index < 5 {
array.append {
print("count: \(count)")
print("index: \(index)")
}
count += 1
index += 1
}
array[0]()
array[4]()
Output:
count: 5
index: 5
count: 5
index: 5
Same case but with some changes:
var array = [() -> ()]()
var count = 0
for index in 0..<5 {
array.append {
print("count: \(count)")
print("index: \(index)")
}
count += 1
}
array[0]()
array[4]()
Output:
count: 5
index: 0
count: 5
index: 4
Count value would be the same in both the cases as we are not explicitly capturing it, i.e 5
In the first case global index variable is used and the result is the last incremented value i.e. 5 and 5
In the second case for loop's index is used and the value is 0 and 4 respectively.
What is the exact difference?
In the first example index is var declared and it is the same variable used each time, in the second it is let declared so in the second example it is a new instance of index that exists in the scope of the for loop for each iteration
I Debugged that code because it looked kinda weird but just let me tell you, the appending and increment line goes well, When you call array0 and array4, the debugger goes to the body of append{} and print those variables. and captures those variable from most easily accessible scope. so in first case, it will capture from the scope of function body which values are actually new 5 and 5 for both count and index.
in second case, it will try to capture if there is a variable count and index initialized, it will find count but wont find so it will check inside the body of array and there it will find the actual value which is 0 in first index and 4 in 5th index.
That's all i can explain, Sorry for bad english
Check Debugger Image Here

Why am I getting a Fatal error when I try removing an element from array inside a loop?

I have an array, I want to do some filtering in it, however, it gives me a runtime error. Is there any alternative way of doing this? (without using closures)
var arr = [4,5,6,7]
for i in 0..<arr.count - 1 {
if arr[i] > 2 {
arr.remove(at: i)
}
}
print(arr)
Think about what your code does.
if arr[i] > 2 { //#2
arr.remove(at: i)
}
}
At #1, it looks at the current number of elements in the array and sets the end value of the loop to 3. So the loop will run from 0 to 3.
At #2, each element in the array is greater than 2, so it gets removed from the array.
At i == 0 the 4 is removed. Now there are 3 elements
At i == 1, the
5 is removed. Now there are 2 elements
At i == 2, it attempts to
fetch an element at index 2, and crashes with an index out of range
error.
You are mutating the array as you attempt to iterate through it. Don't do that.
As others have said, use filter instead:
arr = arr.filter { $0 <= 2 }
If you really want to use a for loop and remove elements via index, loop through the array backwards:
var arr = [4,5,6,7]
for index in stride(from: arr.count-1, to: -1, by: -1) {
let thisValue = arr[index]
print("arr[\(index)]=\(thisValue)")
if thisValue > 2 {
arr.remove(at: index)
print("->> removing \(thisValue) from arr at index \(index)")
}
}
print("\nAfter for loop, arr contains \(arr.count) items")
arr.forEach {
print($0)
}
That ouputs:
arr[3]=7
->> removing 7 from arr at index 3
arr[2]=6
->> removing 6 from arr at index 2
arr[1]=5
->> removing 5 from arr at index 1
arr[0]=4
->> removing 4 from arr at index 0
After for loop, arr contains 0 items
This is a great example of why mutation is best avoided.
If you're manipulating an array and iterating over it at the same time, the index values are going to be invalid, because what was at index 4, will now be at index 3 if you delete something at position 1.
You can do it without 'using closures':
var idxToRemove: [Int] = []
for (idx, i) in arr.enumerated() {
if i > 2 {
idxToRemove.append(idx)
}
}
for i in idxToRemove.reversed() {
arr.remove(at: i)
}
But what you want is: let arr = [4,5,6,7].filter { $0 <= 2 }
var arr = [4, 5, 6, 7]
arr = arr.filter { $0 <= 2 }
print(arr)

Execute a special for loop

I have a array:
let array = [1,2,3,4,5]
I need to perform a for loop on this array where at each number I need to add +90, and -90
now here the issue:
in a normal for loop the code will be like this:
for i in array {
let plus = i + 90
append.newArray(plus)
let minus = i - 90
append.newArray(plus)
}
I need to switch the plus and minus..
at the first cycle I need to append to the newArray plus and minus..... but for the second cycle I must append in order minus and plus.
is there any way to switch the for loop to alternate between the plus and minus -- minus plus.
You need to use it, as I understand, for odd and even values in source array, so you can use something like this:
let array = [1, 2, 3, 4, 5]
var newArray: [Int] = []
func plusValue(_ value: Int) {
let plus = value + 90
newArray.append(plus)
}
func minusValue(_ value: Int) {
let minus = value - 90
newArray.append(minus)
}
for (value, index) in array.enumerated() {
if index.isMultiple(of: 2) { // even
minusValue(value)
plusValue(value)
} else { // odd
plusValue(value)
minusValue(value)
}
}
Just need to understand what you need to use for even and for odd indexies.
Here is one way to do it using a for loop over the indices
let array = [1,2,3,4,5]
var output = [Int]()
for index in array.indices {
let value = index % 2 == 0 ? 90 : -90
output.append(array[index] + value)
output.append(array[index] - value)
}
another option is to use reduce(into:)
let output = array.enumerated().reduce(into: []) {
let factor = $1.offset % 2 == 0 ? 1 : -1
$0.append(contentsOf: [$1.element + factor * 90, $1.element - factor * 90])
}

the implementation of the arraylists

fun main(args:Array<String>){
var arraylist= ArrayList<String>()
arraylist.add("jena")
arraylist.add("Laya")
arraylist.add("Hussein")
arraylist.add("Ahmed")
println("First name:"+ arraylist.get(0))
arraylist.set(0," Laya Hussein")
println(" all element by object")
for ( item in arraylist){
println(item)
}
println(" all element by index")
for( index in 0..arraylist.size-1){
println(arraylist.get(index))
}
}
My question why we add -1 for iterating?
it is not clicking with me.
Because if you don't add the -1, it will iterate through 0 to the size of the list. Which means, if we have a list of size 5, it will iterate:
0, 1, 2, 3, 4, 5
And obviously index 5 is not a valid index here, so we need to make sure we don't iterate too far.
strong textArrays in Kotlin have zero-based index. To iterate through the whole array we need to use indexes from 0 to array.size()-1. Operator .. means including both ranges, so to iterate through the whole array:
for (index in 0..arraylist.size - 1) {
// ...
}
We can use function until to avoid using arraylist.size-1, it includes left range but excludes right range:
for (index in 0 until arraylist.size) {
// ...
}
Also we can use shorter version of for loop just to iterate through the all elements of array:
for (item in arraylist) {
// ...
}
The indices of the array are zero based. This means that in arrayOf("A", "B", "C")
A has index 0, B has index 1 and C has index 2. So the last valid index is the array's size - 1 which is 3 - 1 = 2
If you don't want to worry about that you can use indices extension property which is an IntRange of all valid indices.
for(index in arraylist.indices) {
println(arraylist[index])
}
Notice the replacment of get with the operator notation [] which makes the code more concise.
If you don't care for the index, avoid the headache alltogether and use forEach
arraylist.forEach {
println(it)
}

In Swift, an efficient function that separates an array into 2 arrays based on a predicate

Note: I'm currently still using Swift 2.2, but open to Swift 3 solutions as well
I'm looking to create a function that operates very closely to filter, except that it keeps the non-matching results as well, and maintains sort order. For instance, say you wanted to filter out numbers divisible by 3 in an array and still keep the list of numbers that aren't divisible by 3.
Option 1: Using filter
With filter, you only get the list of numbers divisible by 3 and the original list stays unchanged. You can then filter the original list again with the opposite predicate, but this is an unnecessary second pass. The code looks like this:
let numbers = [1,2,3,4,5,6,7,8,9,10]
let divisibleBy3 = numbers.filter { $0 % 3 == 0 } // [3,6,9]
let theRest = numbers.filter { $0 % 3 != 0 } // [1,2,4,5,7,8,10]
It's true that this is pretty readable, but the fact that it does 2 passes seems inefficient to me, especially if the predicate were more complicated. That's twice as many checks as are actually needed.
Option 2: Using custom separate function in Collection extension
My next attempt was extending Collection and making a function I called separate. This function would take the collection and go through the elements one at a time and add them to either the matching list or the non-matching list. The code looks like this:
extension Collection {
func separate(predicate: (Generator.Element) -> Bool) -> (matching: [Generator.Element], notMatching: [Generator.Element]) {
var groups: ([Generator.Element],[Generator.Element]) = ([],[])
for element in self {
if predicate(element) {
groups.0.append(element)
} else {
groups.1.append(element)
}
}
return groups
}
}
I can then use the function like this:
let numbers = [1,2,3,4,5,6,7,8,9,10]
let groups = numbers.separate { $0 % 3 == 0 }
let matching = groups.matching // [3,6,9]
let notMatching = groups.notMatching // [1,2,4,5,7,8,10]
This is also pretty clean, but the only thing I don't like is that I'm using a tuple as a return type. Maybe others will disagree, but I'd prefer returning the same type as self for chaining. But technically, you can just grab either .matching or .notMatching, which is the same type as self, and you can chain off of either of them.
Option 3: Using a custom, mutating removeIf function in Array extension
My issue with separate returning a tuple led me to try to make a function that would modify self by removing the matches as it found them and adding them to a new list, and returning the matches list at the end. The returned list is your matches, and the array is trimmed of those values. Order is preserved in both arrays. The code looks like this:
extension Array {
mutating func removeIf(predicate: (Element) -> Bool) -> [Element] {
var removedCount: Int = 0
var removed: [Element] = []
for (index,element) in self.enumerated() {
if predicate(element) {
removed.append(self.remove(at: index-removedCount))
removedCount += 1
}
}
return removed
}
}
And it is used like this:
var numbers = [1,2,3,4,5,6,7,8,9,10]
let divisibleBy3 = numbers.removeIf { $0 % 3 == 0 }
// divisibleBy3: [3,6,9]
// numbers: [1,2,4,5,7,8,10]
This function had to be implemented in an extension of Array, because the concept of removing an element at a particular index doesn't apply to regular Collections (an Array is defined as public struct Array<Element> : RandomAccessCollection, MutableCollection, and it directly defines the remove(at:) function, rather than getting it from inheritance or a protocol).
Option 4: Combination of Option 2 and 3
I'm a big fan of code reuse, and after coming up with Option 3, I realized I could probably reuse the separate function from Option 2. I came up with this:
extension Array {
mutating func removeIf(predicate: (Element) -> Bool) -> [Element] {
let groups = self.separate(predicate: predicate)
self = groups.notMatching
return groups.matching
}
}
And it's used just like in Option 3.
I was concerned with performance, so I ran each Option through XCTest's measure with 1000 iterations. These were the results:
Option 1: 9 ms
Option 2: 7 ms
Option 3: 10 ms
Option 4: 8 ms
Option 5: Based on negaipro's answer
I knew about partition, but I wasn't going to consider it because it didn't preserve the sort order. negaipro's answer is essentially partition, but it got me thinking. The idea with partition is to swap elements that match with the pivot point, thus ensuring that everything on one side of the end pivot point will all match the predicate and the other side doesn't. I took that idea and changed the action to "move to the end". So matches are removed from their spot and added to the end.
extension Array {
mutating func swapIfModified(predicate: (Element) -> Bool) -> Int {
var matchCount = 0
var index = 0
while index < (count-matchCount) {
if predicate(self[index]) {
append(remove(at: index))
matchCount += 1
} else {
index += 1
}
}
return count-matchCount
}
}
Under my initial tests using an array with 10 numbers, it was comparable to the other Options. But I was concerned with the performance of the line append(remove(at: index)). So I tried all the Options again with arrays going from 1 to 1000, and this option was definitely the slowest.
Conclusion:
There isn't a big performance difference between these options. And since Option 4 was faster than Option 3 and reuses the code from Option 2, I'm inclined to throw out Option 3. So I'm leaning towards using plain old filter when I don't care about the unfiltered results (and, likewise, for when I don't care about the filtered results, since it's just using the opposite predicate), and then using either separate or removeIf when I care about keeping both the filtered and unfiltered results.
Question:
So, am I missing something built into Swift that does this already? Is there a better way to accomplish this? Is my extension syntax missing anything (anything that could make it apply this concept to more areas, for example)?
Technically, this is not guaranteed to preserve order, but it does.
Dictionary(grouping: numbers) { $0.isMultiple(of: 3) }
https://github.com/apple/swift/blob/master/stdlib/public/core/NativeDictionary.swift
Swift 4 Solution
partition(by:)
It reorders the origin array and returns start index of subarray satisfies the predicate.
In this example it returns 7.
0..<7 elemets aren't divisible by 3 and 7..n-1 elements are divisible by 3.
var numbers = [1,2,3,4,5,6,7,8,9,10]
let partition = numbers.partition(by: { $0 % 3 == 0 })
let divisibleBy3 = Array(numbers[..<partition]) //[3,6,9]
let theRest = Array(numbers[partition...]) //[1,2,4,5,7,8,10]
let objects: [Int] = Array(1..<11)
let split = objects.reduce(([Int](), [Int]())) { (value, object) -> ([Int], [Int]) in
var value = value
if object % 2 == 0 {
value.1.append(object)
} else {
value.0.append(object)
}
return value
}
There is a new Swift Algorithms open-source for sequence and collection algorithms, along with their related types.
You can use the stable partition from there
Methods for performing a stable partition on mutable collections, and for
finding the partitioning index in an already partitioned collection.
The standard library’s existing partition(by:) method, which re-orders the
elements in a collection into two partitions based on a given predicate, doesn’t
guarantee stability for either partition. That is, the order of the elements in
each partition doesn’t necessarily match their relative order in the original
collection. These new methods expand on the existing partition(by:) by
providing stability for one or both partitions.
// existing partition(by:) - unstable ordering
var numbers = [10, 20, 30, 40, 50, 60, 70, 80]
let p1 = numbers.partition(by: { $0.isMultiple(of: 20) })
// p1 == 4
// numbers == [10, 70, 30, 50, 40, 60, 20, 80]
// new stablePartition(by:) - keeps the relative order of both partitions
numbers = [10, 20, 30, 40, 50, 60, 70, 80]
let p2 = numbers.stablePartition(by: { $0.isMultiple(of: 20) })
// p2 == 4
// numbers == [10, 30, 50, 70, 20, 40, 60, 80]
Since partitioning is frequently used in divide-and-conquer algorithms, we also
include a variant that accepts a range parameter to avoid copying when mutating
slices, as well as a range-based variant of the existing standard library
partition.
The partitioningIndex(where:) method returns the index of the start of the
second partition when called on an already partitioned collection.
let numbers = [10, 30, 50, 70, 20, 40, 60]
let p = numbers.partitioningIndex(where: { $0.isMultiple(of: 20) })
// numbers[..<p] == [10, 30, 50, 70]
// numbers[p...] = [20, 40, 60]
// swap and return pivot
extension Array
{
// return pivot
mutating func swapIf(predicate: (Element) -> Bool) -> Int
{
var pivot = 0
for i in 0..<self.count
{
if predicate( self[i] )
{
if i > 0
{
swap(&self[i], &self[pivot])
}
pivot += 1
}
}
return pivot
}
}
This is my code and the concept is.. reduce memory usage.
I checked that 'swapIf' is 4-times faster than 'removeIf'.
Solution A
For fewer elements this may be fastest.
extension Array {
func stablePartition(by condition: (Element) -> Bool) -> ([Element], [Element]) {
var matching = [Element]()
var nonMatching = [Element]()
for element in self {
if condition(element) {
matching.append(element)
} else {
nonMatching.append(element)
}
}
return (matching, nonMatching)
}
}
Usage
let numbers = [1,2,3,4,5,6,7,8,9,10]
let (divisibleBy3, theRest) = numbers.stablePartition { $0 % 3 == 0 }
print("divisible by 3: \(divisibleBy3), the rest: \(theRest)")
// divisible by 3: [3, 6, 9], the rest: [1, 2, 4, 5, 7, 8, 10]
Solution B
For many elements this may be faster, because of fewer allocations. I have not measured performance.
extension Array {
public func stablePartition(by condition: (Element) throws -> Bool) rethrows -> ([Element], [Element]) {
var indexes = Set<Int>()
for (index, element) in self.enumerated() {
if try condition(element) {
indexes.insert(index)
}
}
var matching = [Element]()
matching.reserveCapacity(indexes.count)
var nonMatching = [Element]()
nonMatching.reserveCapacity(self.count - indexes.count)
for (index, element) in self.enumerated() {
if indexes.contains(index) {
matching.append(element)
} else {
nonMatching.append(element)
}
}
return (matching, nonMatching)
}
}
In WWDC 2018 session Embracing Algorithm they mention the function stablePartition, you can take a look here https://github.com/apple/swift/blob/master/test/Prototypes/Algorithms.swift
extension Collection where Self : MutableCollectionAlgorithms {
#discardableResult
mutating func stablePartition(
isSuffixElement: (Element) throws -> Bool
) rethrows -> Index {
return try stablePartition(
count: count, isSuffixElement: isSuffixElement)
}
/// Moves all elements satisfying `isSuffixElement` into a suffix of the collection,
/// preserving their relative order, returning the start of the resulting suffix.
///
/// - Complexity: O(n) where n is the number of elements.
/// - Precondition: `n == self.count`
fileprivate mutating func stablePartition(
count n: Int, isSuffixElement: (Element) throws-> Bool
) rethrows -> Index {
if n == 0 { return startIndex }
if n == 1 {
return try isSuffixElement(self[startIndex]) ? startIndex : endIndex
}
let h = n / 2, i = index(startIndex, offsetBy: h)
let j = try self[..<i].stablePartition(
count: h, isSuffixElement: isSuffixElement)
let k = try self[i...].stablePartition(
count: n - h, isSuffixElement: isSuffixElement)
return self[j..<k].rotate(shiftingToStart: i)
}
}

Resources