Find Array Item Number in a For Statement - arrays

I'm using a for statement to loop through items in an array to find the item's value. On occasion however, I need to find out what that item's count is in the array (not just the item value), but can't seem to figure out how to do this. Below is what I've been trying which has given me some sort of result, but not what I need, everything else I've tried has resulted in an error:
for elements in myArray {
println(elements) // gives me the value
println(elements.items) // gives me nil
}
Any help would be much appreciated.

Well an easy way to do that is:
for index in 0..<myArray.count {
println(myArray[index]) // value
println(index) // count
}
If you know what kind of value you're looking for, you can also use the find() method:
let value = 13
if let index = find(myArray, value) {
println(myArray[index]) // item in the array with the value you were searching for
}

You can use enumerate() to get the elements of an array (or any
sequence) together with the corresponding index:
for (index, element) in enumerate(myArray) {
println(element) // current element
println(index) // index of current element
}

Related

How to solve Fatal Error: Index out of range error in swift?

In this piece of code, when the iteration position reach 13 out of an array with 20 elements, it crashes with the index out of range error.
let counterHeaders = headers.count
for value in 0..<(counterHeaders){
if headers[value] == "" {
headers.remove(at: value)
}
}
Note: counterHeaders variable was created to check how many values was in headers array
You just need to iterate your indices in reverse order when removing items in your collection.
for value in headers.indices.reversed() {
if headers[value] == "" {
headers.remove(at: value)
}
}
Note also there is a mutating method that accepts a predicate called removeAll(where:):
headers.removeAll(where: \.isEmpty)

Get first entry in Swift array

I can't seem to find much online, but how can I get the first (and then second and third, later on) entry of an array?
My array is being saved to UserDefaults elsewhere and then pulled for use here.
Thanks!
Did you mean to loop through the elements? You can use for in or forEach for that.
var array: [MyType]
for element in array {
print(element)
}
array.forEach { element in
print(element)
}
Maybe you are trying to iterate value from continually with index also
Here is two way you can get first index value than second index value third index value with index also . hope you will get your result .
First way :
var stringArray = ["a","b","C","D","a","i","x","D"]
for (index, element) in stringArray.enumerated() {
print("Item \(index): \(element)")
}
Another way :
for index in 0 ..< stringArray.count {
print(stringArray[index])
}
let me know if its help you.

Is it safe to iterate an array while modifying it?

I know you shouldn't, I kind of know why. But I mean I don't understand my own code once I am trying really to think what's going on.
So I have an array with bunch of objects. I am iterating over it and once I find an object with specific type, I remove it from the array, and add another object into the array. So something like this:
var arr = parent.allchildren() //getting all the children in array
for ele in arr{
if(ele==somethingHere){
parent.remove(ele)
parent.add(new ele) //add new child into child array
}
}
If I have an array of 1,2,3,4,5, and I remove 3 and add a 6 while iterating, the actual array would be 1,2,4,5,6 but the array I am iterating would still be 1,2,3,4,5.
Which I think it would be fine, because at the end I still get what I want, which removed the element and added the element I need. However modifying the list while iterating it is bad and you shouldn't do that, but for my case I think it does what I need. What could be the potential issue in my case that I can't see?
One thing you may want to think about doing is making all of the changes at the end of the iteration. Instead of making the changes one by one, record the changes you want to make while iterating, and then actually make those changes once your loop is finished.
For example, you could make an array of elements to remove, and an array of elements to add.
//Our array where we record what we want to add
var elementsToAdd = [Any]()
//Our array of what elements we want to remove. We record the index at
//which we want to remove the element from the array
var indexesToRemoveAt = [Int]()
//Getting all the children in array
var arr = parent.allchildren()
//Enumerating an array allows us to access the index at which that
//element occurs. For example, the first element's index would be 0,
//the second element's index would be 1, the third would be 2, and so
//on
for (index,ele) in arr.enumerated() {
if(ele == somethingHere) {
indexesToRemoveAt.append(index)
elementsToAdd.append(newEle)
}
}
//Now that we have recorded the changes we want to make, we could make
//all of the changes at once
arr.remove(at: indexesToRemoveAt)
arr.append(contentsOf: elementsToAdd)
Note that removing array elements at multiple indexes would require the following extension to Array. If you wanted to avoid creating this extension, you could always just loop through the array of indexes and tell the array to remove at each individual index. All this extension function is really doing is looping through the indexes, and removing the array element at said index.
Array extension to remove elements at multiple indexes:
extension Array {
//Allows us to remove at multiple indexes instead of just one
mutating func remove(at indexes: [Int]) {
for index in indexes.sorted(by: >) {
if index <= count-1 {
remove(at: index)
}
}
}
}
I just tested in a playground with the following code:
var arr = ["hi", "bye", "guy", "fry", "sky"]
for a in arr {
if arr.count >= 3 {
arr.remove(at: 2)
}
print(a)
}
print(arr)
This prints:
hi
bye
guy
fry
sky
["hi", "bye"]
So it looks like when you use a for-in loop in Swift, the array is copied and changes you make to it will not affect the array you are iterating over. To answer your question, as long as you understand that this is the behavior, there's nothing wrong with doing this.

Search if a specific attribute in all the elements of an array match a condition

I'm working with Swift, SpriteKit and Xcode 6,
I have an array of a SKSpriteNode class :
class EnemyVehicle: SKSpriteNode {
}
var vehicles = [EnemyVehicle]()
So I can add elements to this array like this:
vehicles.append(EnemyVehicle(imageNamed:"mySprite"))
And the superclass SKSpriteNode contains an attribute which is position.y, and I can access it in every element of my array with vehicle[x].position.y.
My question is: is it possible to test every specific attribute in an array (here position.y) and watch if it match the conditions? For example, if I want a condition which is true only when all of the position.y values of all my elements in my array are superior than 0? I know I could do it with a loop, but is there another easier way to do it?
Sounds like you want reduce.
Reduce takes a starting value, and then a closure that takes the running value and the next element of the array, and combines these two elements together, carrying that result forward to combine with the next element.
For example:
let a = [1,2,3]
// starting with zero, add each element to a total
let sum = a.reduce(0) { total, i in total + i }
// sum = 6
To check if all elements in an array match a given criteria, you want a combining function that checks the property and returns true or false, anding that with the previous criteria:
// assuming you’re ok for true for an empty array:
let allAboveGround = vehicles.reduce(true) {
previous, vehicle in
previous && vehicle.position.y > 0
}
There’s one downside to this – as soon as you hit a value that is false, you could stop right there because the overall value cannot be true. Reduce doesn’t cater for this so you may want to write a loop, or maybe an all function that wraps a loop, that quits early under these conditions:
func all<S: SequenceType>(source: S, pred: S.Generator.Element->Bool) -> Bool {
for x in source {
if !pred(x) { return false }
}
return true
}
let allAboveGround = all(vehicles) { $0.position.y > 0 }

How can i splice current index in a foreach?

I have this foreach loop to check for collision and i want platform(movieclip) to be removed in case of collision. So far i've come up with this:
if (mcContent.mcPlayer.y + mcContent.mcPlayer.height > platformCloud.y)
{
mcContent.mcPlayer.y = platformCloud.y - mcContent.mcPlayer.height - 1;
jump();
mcContent.removeChild(platformCloud);
//platformsCloud.splice(platformCloud);
}
What this is doing is, removing the movieclip (ok so far so good) but without the splice, when the loop runs again through the array it is still there. So with the splice that is commented out there's 1 little problem, it removes all the movieclips from the array, apprently.
How can i splice only the current index that is being checked?
.splice() accepts a start index and an amount of items to remove, not the object you want to remove from the array.
Parameters
startIndex:int — An integer that specifies the index of the element in the array where the insertion or deletion begins. You can use a negative integer to specify a position relative to the end of the array (for example, -1 is the last element of the array).
deleteCount:uint — An integer that specifies the number of elements to be deleted. This number includes the element specified in the startIndex parameter. If you do not specify a value for the deleteCount parameter, the method deletes all of the values from the startIndex element to the last element in the array. If the value is 0, no elements are deleted.
You want to do this:
var index:int = platformsCloud.indexOf(platformCloud);
platformsCloud.splice(index, 1);
Why not just create a new array of the items to keep? Use Array.push to add new items. This may actually be more efficient than modifying the existing array. It also doesn't require keeping track of indices (which are required to use Array.splice).
Example code:
var keptPlatforms = [];
// do stuff
if (mcContent.mcPlayer.y + mcContent.mcPlayer.height > platformCloud.y)
{
mcContent.mcPlayer.y = platformCloud.y - mcContent.mcPlayer.height - 1;
jump();
mcContent.removeChild(platformCloud);
} else {
keptPlatforms.push(platformCloud);
}
// later, after this cycle, use the new Array
platformClouds = keptPlatforms;
Now, the reason platformsCloud.splice(platformCloud) removes all items is because the first argument is coerced to an integer so it is equivalent to platformsCloud.splice(0) which says "remove the 0th-indexed item to the end of the array". And, this does indeed clear the array.
To use Array.splice, you'd have to do something like:
// inside a loop this approach may lead to O(n^2) performance
var i = platformClouds.indexOf(platformCloud);
if (i >= 0) {
platformClouds.splice(i, 1); // remove 1 item at the i'th index
}

Resources