index(of: Element) on 2d array’s outside array

I have a 2d array and am trying to access the index of one of the elements of the outside array (therefore the index for a contained 1d array) as shown in the code below:

let int2dArray = [[3, 2], [8, 4]]
for i in int2dArray {
    for j in i {
        let iCurrentIndex = int2dArray.index(of: i)
    }
}


When I try to use index(of: Element), I get the following error message: Cannot invoke 'index' with an argument list of type '(of: Array<Int>)’. I also notice in the code completion suggestions that index(of:) doesn’t show up, but index(where: (Element) -> Bool) does show up. Closures are still a relatively new concept to me (I’m not a total newbie to iOS development but not as experienced yet), so I’m not sure exactly what this method would take as a parameter. Why is this? Does any of this have to do with the element's conformance with Equatable (which is required for this method)?


In Swift 2.x and 1.x (and C++), I could use a C-style for loop and accomplish this because i (in this case) was the actual array index, like so:

for var i = 0; i < int2dArray.count; i++ {
  for var j = 0; j < int2dArray[i].count; j++ {
       let iCurrentIndex = i
  }
}


Any suggestions?

Thanks!

Accepted Reply

It actually looks like a bug in the compiler. You should submit a bug report with the 1st code fragment.


However, if you just want to get hold of the current index, you can do it more easily like this:


let int2dArray = [[3, 2], [8, 4]]
for (iCurrentIndex, i) in int2dArray.enumerated () {
  for j in i {
       print (iCurrentIndex, i) // etc
  }
}


That "enumerated" method allows you to get the index and the element at the same time.


Edit: Submitted as bug 28294667.

Replies

It actually looks like a bug in the compiler. You should submit a bug report with the 1st code fragment.


However, if you just want to get hold of the current index, you can do it more easily like this:


let int2dArray = [[3, 2], [8, 4]]
for (iCurrentIndex, i) in int2dArray.enumerated () {
  for j in i {
       print (iCurrentIndex, i) // etc
  }
}


That "enumerated" method allows you to get the index and the element at the same time.


Edit: Submitted as bug 28294667.

That "enumerated" method allows you to get the index and the element at the same time.

Regardless of the following, this is definitely the right way to solve macuser1984’s problems (nice handle btw!). Everything below is just FYI.

index(of:)
won’t work because it requires
Element
to be equatable and
int2dArray
’s elements are of type
[Int]
.
[Int]
values can be compared, they don’t conform to
Equatable
.
let a1 = [1, 2, 3]
let a2 = [1, 2, 3]

func isEquals<X>(_ x: X, _ y: X) -> Bool where X : Equatable {
    return x == y
}

print(a1 == a2)
print(isEquals(a1[0], a2[0]))
print(isEquals(a1, a2))
//^^^^^^^^^^^ Argument type '[Int]' does not conform to expected type 'Equatable'

For more background on this, look up “conditional conformance” in the Generics Manifesto.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I revised my bug report to change it to a complaint about the misleading error message.

QuinceyMorris - I just tried this solution with my actual code (that's more complicated than the simple example I wrote here), and it now works as I expected it to. It actually cleaned up my code and made it easier to read!


eskimo - Thanks for the extra information, especially the example!