Comparing elements at different indices in array Swift - arrays

In swift, I want to compare two different indexes in the same array. Right now, My code is something like:
var myArray:[String] = ["1" , "1", "2"]
for i in myArray{
if(myArray[i] == myArray[i + 1]){
// do something
}
}
From this, I get an error:
Cannot convert value of type 'String' to expected argument type 'Int'
How do I go about fixing this?

Not a direct answer to your question but if what you want is to compare adjacent elements in a collection what you need is to zip the collection with the same collection dropping the first element:
let array = ["1" , "1", "2"]
for (lhs,rhs) in zip(array, array.dropFirst()) {
if lhs == rhs {
print("\(lhs) = \(rhs)")
print("do something")
} else {
print("\(lhs) != \(rhs)")
print("do nothing")
}
}
This will print:
1 = 1
do something
1 != 2
do nothing

For-each construction (for i in array) does not provide you with an index, it takes elements from a sequence.
You may want to use ranges like this to aquire indices:
for i in 0 ..< array.count

Related

Not able to change the value of element of array in for-loop in Swift

I want to add one to the array values that are next to the current iteration.
Although at the end result is right, if we see the print(item) result, it still prints the old values.
var arr3 = [1,2,3]
for (index,item) in arr3.enumerated() {
if index+1 == arr3.count {
// Do nothing
} else {
arr3[index + 1] = arr3[index+1] + 1
}
print(item)
}
print(arr3)
Result :
1
2
3
[1,3,4]
Expected :
1
3
4
[1,3,4]
How is this possible?
You might expect the loop using enumerated() to behave the same as looping over the indices and having let item = arr3[index]:
for index in arr3.indices {
let item = arr3[index]
print(item)
if index+1 != arr3.count {
arr3[index + 1] += 1
}
}
However, this is not true. enumerated() produces an EnumeratedSequence<[Int]>. (See the source code for EnumeratedSequence and enumerated()). To create an EnumeratedSequence, the original array arr3 is passed to its initialiser:
public func enumerated() -> EnumeratedSequence<Self> {
return EnumeratedSequence(_base: self)
}
As you may know, Array is a (copy-on-write) value type. When you modify arr3 in the loop, a modified copy is created and assigned to arr3, and the array that the EnumeratedSequence has (i.e. the array over which the loop is iterating), is unaffected. enumerated() is sort of creating a "snapshot" of the array at the time when you called it, so all the print(item) will only print the old items.

Swift - Smart way to cycle through an Array of Array [[Int]]

I use an Array of Array [[Int]] storing coordinates in a map.
I for example want to replace all "2" with "1".
For this I created 2 for loops which define the array space and check for the content.
This is not very flexible and only works with arrays of the defined size.
private func remove2fromArray(currentArray: [[Int]]) -> [[Int]] {
var newArray : [[Int]] = currentArray
for section in 0...14 {
for row in 0...19 {
if newArray[section][row] == 2
{ newArray[section][row] = 1 }
}
}
return newArray
}
Is there a way to just scan through the content of the array to replace the numbers?
e.g.
currentArray.findAndReplace(find:2, replace: 1) or similar, that works with [[Int]]?
You can do it this way:
let result = array.map { subarray in
subarray.map { integer -> Int in
if integer == 2 {
return 1
} else {
return integer
}
}
}
Even shorter:
let result = array.map {
$0.map { integer in
return integer == 2 ? 1 : integer
}
}
And a one-liner:
let result = array.map { $0.map { $0 == 2 ? 1 : $0 } }
I'll try to explain what's happening here in simple words: What map does is that it goes through the array elements one by one and applies a function on the element.
In our example, the first map iterates over the outer array elements, so $0 here refers to the inner arrays (one after one).
The second map iterates over the inner arrays' elements. So $0 in the inner map refers to the each element of the inner arrays' elements.

Check if array contains element in Swift 4

I am trying to check if array categories contain number 1 as Int since categories = [Int]() for example categories = {1, 2, 3, 4, 5}
I have tried the below code which gives me error Binary operator '==' cannot be applied to operands of type 'Any' and 'Int'
if categories.contains (where: {$0 == 1}) {
// 1 is found
}
also tried it without the where and brackets as below which gives me the same error
if categories.contains { $0 == 1 } {
// 1 is found
}
I tried using just the element as below which gives me error Missing argument label 'where:' in call
if categories.contains(1) {
// 1 is found
}
How can I do that?
It seems like your category array is of type Any
Ways to fix it
You can declare your array as an Int array
var categories: [Int]
OR
You can change the following piece of code
if categories.contains { $0 == 1 } {
// 1 is found
}
to
if categories.contains { ($0 as! Int) == 1 } {
// 1 is found
}
Note: This method might cause your app to crash if your category array has an element other than of type Int
it is working See my output in PlayGround
Code used:
var categories : [Int] = [0,1,2,3,4,5,6,7,8,9]
if categories.contains(5)
{
print("Yes it contains")
}
else
{
print("it do not")
}
and also This condition is working
if categories.contains (where: {$0 == 1}) {
print("yes")
}
see your Array Declaration I think there is main Issue
Declaration 1 :
var categories = [Int]()
categories = [0,1,2,3,4,5,6,7,8,9]
Declaration 2 :
var categories : [Int] = [0,1,2,3,4,5,6,7,8,9]
Regarding error message
Binary operator '==' cannot be applied to operands of type 'Any' and 'Int'
Your array is not an Int array instead it contains Any so it needs typecasting before comparision. Declaration of array is also wrong use [] instead of {}. And typecast object as an int ($0 as! Int) == 1 (I'm using force casting here because I know its an Int array).
There are many ways to check if array contains any element.
1> Just try to get the index of element with guard if index is nil means array doesn't contain the element. Although you didn't declare array in right way still I'm considering it a valid array.
let categories: [Int] = [1, 2, 3, 4, 5]
guard categories.index(of: 1) != nil else {
print("Doesn't Contain")
return
}
print("Contains")
2> Use contains method
if (categories.contains(1)) {
print("Contains")
}
else {
print("Doesn't Contain")
}
3> Not Recommended for this case But still you can get this
let result = categories.filter({$0 == 1})
if result.count == 0 {
print("Doesn't Contain")
}
else {
print("Contains")
}
filter returns an array of element which matches with condition. So that if there are multiple 1 in array so it will give you an array of all elements. And $0 describes the object while enumerating the array.
4> Not Recommended for this case
let contains = categories.contains(where: {$0 == 1})
if contains {
print("Contains")
}
else {
print("Doesn't Contain")
}
Thanks to your comments made me check the declaration of the array and the problem was that was declared as [Any] after I get it's value from the UserDefaults. I have checked and found the solution on How do I save an Int array in Swift using NSUserDefaults?
// old declaration
let categories = userDefaults.array(forKey:"categories") ?? [Int]()
// new correct declaration
var categories = [Int]()
if let temp = userDefaults.array(forKey:"categories") as? [Int] {
categories = temp
}

Kotlin: how to create a 2D Array of the type String

i am learning kotlin. i need to create a 2D array which can hold words , special chars and numbers .some where i found this piece of code
THIS
The problem with this is that it can hold only Int .
When i tried replacing keyword "IntArray" with "string". it returned an error
ERROR
Can someone help me create a 10x8 Arrray which can hold strings in Kotlin
There's no StringArray in Kotlin (here's an explanation why), use Array<String> instead.
If you can provide the array items as you create the arrays, then creating the array can be done as:
val result = Array(10) { i ->
Array(8) { j ->
"the String at position $i, $j" // provide some initial value based on i and j
}
}
println(result[0][3]) // Prints: the String at position 0, 3
Otherwise, you can either use some default String value:
val result = Array(10) { Array(8) { "" } }
Or create the inner arrays filled with null values (note: you will have to deal with nullability, you won't be able to use the items as non-null values):
val result = Array(10) { arrayOfNulls<String>(8) } // The type is `Array<Array<String?>>
result[0][0] = "abc"
println(result[0][0]!!.reversed()) // Without `!!`, the value is treated as not-safe-to-use
You can also use Array<Array<String>>. Note that the compiler can automatically infer this type, but specifying the type may help you understand better what's going on. Here is an example with output:
fun main() {
// Create the 2D array of Strings
val string2DArray: Array<Array<String>> = arrayOf(
arrayOf("apple", "orange", "avocado", "mango", "banana"),
arrayOf("_", "!", ":", "?"),
arrayOf("1", "2", "3", "4", "5", "10"))
// Print the 2D array
string2DArray.forEach {
it.forEach { it -> print("$it, ") }
println()
}
// Access an individual String using index notation.
println("My favorite fruit is: ${string2DArray[0][2]}")
}
Output:
apple, orange, avocado, mango, banana,
_, !, :, ?,
1, 2, 3, 4, 5, 10,
My favorite fruit is: avocado
When you convert Java codes to Kotlin, sometimes IDE cannot convert it the way it is expected.
Most the of the time I got code as
Array(x) { arrayOf(ArrayList<String>(y)) }
but this code always throw ArrayIndexOutOfBoundsException exception such as
java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
So as #hotkey suggested you can use below approach which is also worked for me;
Array(x) { Array(y) { ArrayList<String>(y) } }

How to Remove Every Other Element in an Array in Swift?

So say I have an array:
var stringArray = ["a","b","c","d","e","f","g","h","i","j"]
Now, how do I delete "a", "c", "e", "g", and "i" (all the even number indexes from the array)?
Thanks!
Instead of using C-style for-loops (which are set to be deprecated in an upcoming version of Swift), you could accomplish this using strides:
var result = [String]()
for i in stride(from: 1, through: stringArray.count - 1, by: 2) {
result.append(stringArray[i])
}
Or for an even more functional solution,
let result = stride(from: 1, to: stringArray.count - 1, by: 2).map { stringArray[$0] }
Traditional
var filteredArray = []
for var i = 1; i < stringArray.count; i = i + 2 {
filteredArray.append(stringArray[i])
}
Functional alternative
var result = stringArray.enumerate().filter({ index, _ in
index % 2 != 0
}).map { $0.1 }
enumerate takes a array of elements and returns an array of tuples where each tuple is an index-array pair (e.g. (.0 3, .1 "d")). We then remove the elements that are odd using the modulus operator. Finally, we convert the tuple array back to a normal array using map. HTH
There are a bunch of different ways to accomplish this, but here are a couple that I found interesting:
Using flatMap() on indices:
let result: [String] = stringArray.indices.flatMap {
if $0 % 2 != 0 { return stringArray[$0] }
else { return nil }
}
Note: result needs to be defined as a [String] otherwise the compiler doesn't know which version of flatMap() to use.
Or, if you want to modify the original array in place:
stringArray.indices.reverse().forEach {
if $0 % 2 == 0 { stringArray.removeAtIndex($0) }
}
In this case you have to call reverse() on indices first so that they're enumerated in reverse order. Otherwise by the time you get to the end of the array you'll be attempting to remove an index that doesn't exist anymore.
Swift 4.2
A function accepting generics and producing reduced result
func stripElements<T>(in array:[T]) -> [T] {
return array.enumerated().filter { (arg0) -> Bool in
let (offset, _) = arg0
return offset % 2 != 0
}.map { $0.element }
}

Resources