Enumerating in reverse with correct indices - arrays

One nice syntax in Swift is the ability to enumerate both the index and entry of an array as a loop like so:
for (index, entry) in enumerate(myArray) {
doSomething(index, entry)
}
And it's also possible to easily start from the end of the array using the reverse condition like this:
for (index, entry) in enumerate(reverse(myArray)) {
doSomething(index, entry)
}
However, the problem with this is that index now counts from the end of the array (i.e- the last element is index zero), meaning that it has to be corrected if I need an index value for the actual location of entry in myArray, which loses some of the elegance of this.
The alternative is to do something like this:
for (var index, entry) in enumerate(reverse(myArray)) {
index = (myArray.count - 1) - index
doSomething(index, entry)
}
It's not the end of the world, but I'm wondering whether there's an alternative that I've overlooked that could allow me to enumerate in reverse, but with the correct index values being returned?

When you apply reverse() to an array, the result is already a new array, naturally the index should reflect the new array. I found another way to enumerate reversely, I suppose this is elegant enough:
let names = ["Jack", "Lucy", "Kate"]
for index in stride(from: count(names) - 1, through: 0, by: -1) {
println("\(index): \(names[index])")
}

This might be a solution:
let myArray = [1, 2, 3, 4]
for index in reverse(0..<myArray.count) {
println("\(index): \(myArray[index])")
}
Edit:
If you really do not want to access your entry via index inside the for body, you might try:
for (index, entry) in zip(reverse(0..<myArray.count), reverse(myArray)) {
println("\(index): \(entry)")
}
or
for (index, entry) in reverse(0..<myArray.count)
.map({ ($0, myArray[$0])}) {
println("\(index): \(entry)")
}
Hope this helps

Don't think to complicated:
for var i = array.count - 1; i >= 0; i-- {
let item = array[i]
}

Related

How to loop through arrays starting at different index while still looping through entire array in swift?

I want to start loop through array at index (say “5” or any other) instead of beginning of the array in swift
for (index, value) in array.enumerate() {
// do something
}
Use dropFirst to ignore the first items:
for (index, value) in array.enumerated().dropFirst(5) {
// your code here
}
Use the where clause
for (index, value) in array.enumerate() where index > 4 { ...
By the way: Update your Swift version. Swift 2 is dead

How to convert String array to Int array in Kotlin?

Kotlin has many shorthands and interesting features. So, I wonder if there is some fast and short way of converting array of string to array of integers. Similar to this code in Python:
results = [int(i) for i in results]
You can use .map { ... } with .toInt() or .toIntOrNull():
val result = strings.map { it.toInt() }
Only the result is not an array but a list. It is preferable to use lists over arrays in non-performance-critical code, see the differences.
If you need an array, add .toTypedArray() or .toIntArray().
I'd use something simple like
val strings = arrayOf("1", "2", "3")
val ints = ints.map { it.toInt() }.toTypedArray()
Alternatively, if you're into extensions:
fun Array<String>.asInts() = this.map { it.toInt() }.toTypedArray()
strings.asInts()
If you are trying to convert a List structure that implements RandomAccess (like ArrayList, or Array), you can use this version for better performance:
IntArray(strings.size) { strings[it].toInt() }
This version is compiled to a basic for loop and int[]:
int size = strings.size();
int[] result = new int[size];
int index = 0;
for(int newLength = result.length; index < newLength; ++index) {
String numberRaw = strings.get(index);
int parsedNumber = Integer.parseInt(numberRaw);
result[index] = parsedNumber;
}
If you use Array.map as other answers suggest, you get back a List, not an Array. If you want to map an array strings to another array results, you can do it directly like this:
val results = Array(strings.size) { strings[it].toInt() }
This is more efficient than first mapping to a List and then copying the elements over to an Array by calling .toTypedArray().
Consider the input like this "" (empty string)
It would be better to do the filtering first. And it is true the return value is list but not array.
If you need an array, add .toTypedArray() or .toIntArray().
fun stringToIntList(data: String): List<Int> =
data.split(",").filter { it.toIntOrNull() != null }
.map { it.toInt() }
val result = "[1, 2, 3, 4, 5]".removeSurrounding("[","]").replace(" ","").split(",").map { it.toInt() }
Found following simplest
strings.chars().toArray()

Remove specific object from array in swift 3

I have a problem trying to remove a specific object from an array in Swift 3. I want to remove item from an array as in the screenshot but I don't know the solution.
If you have any solutions please share with me.
Short Answer
you can find the index of object in array then remove it with index.
var array = [1, 2, 3, 4, 5, 6, 7]
var itemToRemove = 4
if let index = array.index(of: itemToRemove) {
array.remove(at: index)
}
Long Answer
if your array elements confirm to Hashable protocol you can use
array.index(of: itemToRemove)
because Swift can find the index by checking hashValue of array elements.
but if your elements doesn't confirm to Hashable protocol or you don't want find index base on hashValue then you should tell index method how to find the item. so you use index(where: ) instead which asks you to give a predicate clouser to find right element
// just a struct which doesn't confirm to Hashable
struct Item {
let value: Int
}
// item that needs to be removed from array
let itemToRemove = Item(value: 4)
// finding index using index(where:) method
if let index = array.index(where: { $0.value == itemToRemove.value }) {
// removing item
array.remove(at: index)
}
if you are using index(where:) method in lots of places you can define a predicate function and pass it to index(where:)
// predicate function for items
func itemPredicate(item: Item) -> Bool {
return item.value == itemToRemove.value
}
if let index = array.index(where: itemPredicate) {
array.remove(at: index)
}
for more info please read Apple's developer documents:
index(where:)
index(of:)
According to your code, the improvement could be like this:
if let index = arrPickerData.index(where: { $0.tag == pickerViewTag }) {
arrPickerData.remove(at: index)
//continue do: arrPickerData.append(...)
}
The index existing means Array contains the object with that Tag.
I used the solutions provided here: Remove Specific Array Element, Equal to String - Swift Ask Question
this is one of the solutions there (in case the object was a string):
myArrayOfStrings = ["Hello","Playground","World"]
myArrayOfStrings = myArrayOfStrings.filter{$0 != "Hello"}
print(myArrayOfStrings) // "[Playground, World]"

When to use enumerate for arrays in Swift?

I noticed strange things happen when you try to remove or mutate array items in a loop. However, when doing it while calling enumerate() on the array, it works as expected. What is the concept behind it and when should we use enumerate()?
To answer the question from the title, you use enumerate() when you need value's index in addition to the value itself:
If you need the integer index of each item as well as its value, use the enumerate() method to iterate over the array instead.
for (index, value) in shoppingList.enumerate() {
print("Item \(index + 1): \(value)")
}
enumerate() provides a safe pattern for modifying array elements while iterating over them:
for (index, (var value)) in shoppingList.enumerate() {
if value == "something" {
shoppingList[index] = "something-else"
}
}

Swift Dictionary of Arrays

I am making an app that has different game modes, and each game mode has a few scores. I am trying to store all the scores in a dictionary of arrays, where the dictionary's key is a game's id (a String), and the associated array has the list of scores for that game mode. But when I try to initialize the arrays' values to random values, Swift breaks, giving me the error below. This chunk of code will break in a playground. What am I doing wrong?
let modes = ["mode1", "mode2", "mode3"]
var dict = Dictionary<String, [Int]>()
for mode in modes
{
dict[mode] = Array<Int>()
for j in 1...5
{
dict[mode]?.append(j)
let array:[Int] = dict[mode]!
let value:Int = array[j] //breaks here
}
}
ERROR:
Execution was interrupted, reason: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP, subcode=0x0).
Your problem is array subscripts are zero-based. So when you write:
var a: [Int] = []
for i in 1...5 {
a.append(42)
println(a[i])
}
you will get a runtime error, because first time around the loop you are subscripting a[1] when there is only an a[0]. In your code, you either need to do for j in 0..<5 or let value = array[j-1].
By the way, even though it’s perfectly safe to do dict[mode]! (since you just added it), it’s a habit best avoided as one of these days your code won’t be as correct as you think, and that ! will explode in your face. There’s almost always a better way to write what you want without needing !.
Also, generally speaking, whenever you use array subscripts you are risking an accidental screw-up by accidentally addressing an out-of-bounds index like here. There are lots of alternatives that mean actually using a[i] is easy to avoid:
If you want the indices for a collection (like an array), instead of:
for i in 0..<a.count { }
you can write
for i in indices(a) { }
If you want to number the elements in an array, instead of
for i in indices(a) { println("item \(i) is \(a[i])" }
you can write
for (i, elem) in enumerate(a) { println("item \(i) is \(elem)") }
If the collection happens to have an Int for an index (such as Array), you can use i as an index, but if it doesn’t (such as String) an alternative to get the index and element is:
let s = "hello"
for (idx, char) in Zip2(indices(s),s) { }
If you want the first or last element of an array, instead of:
if a.count > 0 { let x = a[0] }
if a.count > 0 { let x = a[a.count - 1] }
you can write
if let first = a.first { let x = first }
if let last = a.last { let x = first }
Prefer map, filter and reduce to for loops in general (but don’t obsess over it, sometimes a for loop is better)

Resources