0

I'm working to convert some of my ObjC code that uses primitive c arrays to Swift arrays. However, using a playground, I've found some strange behaviors.

For instance, the following is perfectly valid in Swift

var largearray : [[Float]] = []
largearray.append([0,1,2])    //3 elements
largearray.append([3,4,5])    //3 elements
largearray.append([6,7,8,9])    //-4- elements
largearray.append([10,11,12])    //3 elements

//pull those back out
largearray[1][0]    //gives 3
largearray[1][2]    //gives 5
//largearray[1][3]    //error
largearray[2][0]    //gives 6
largearray[2][2]    //gives 8
largearray[2][3]    //gives 9
largearray[3][0]    //gives 10

I don't understand how it's possible to have a mixed row lengths is Swift. Can someone explain what's going on here, because the documentation doesn't go into that kind of detail. I'm curious if it is even storing a contiguous Float array behind the scenes or not.

Then another question I have is about accessing rows or columns. In Swift I see that I can access an entire row using largearray[0] gives [0,1,2], just as largearray[2] gives [6,7,8,9]. Which isn't how c arrays are indexed. (If I just specified one index for a 2D c-array, it would act as a sequential index row by column. So, is there some way to access an entire column in swift? In c, and Swift, largearray[][2] is invalid. But I'm curious if there is some technique not mentioned in the docs, since it seems obvious that Swift is keeping track of extra information.

I should add that I will be making use of the Accelerate framework. So if any of the above "strange" ways of using a Swift array will cause performance issues on massive arrays, let me know.

7
  • I can't tell you for certain because I haven't looked at the code for Swift arrays, but I'm pretty sure they behave a lot more like NSArray than C arrays. You can have different lengths because the outer array stores pointers to the inner arrays. The reason [1][3] gives an error is because it finds the array at index 1 and tries to get the index 3 of that one, but that array only has 3 items. In C it probably translates 1,3 to an index in a linear array and finds that object, even if it technically is the first object in the next array ([2][0]) Commented Feb 12, 2016 at 19:46
  • As for your second question, a solution is var otherArray = largearray.map({$0[2]}) to give you a column array back... Commented Feb 12, 2016 at 19:48
  • So that's part of my question. Is a Swift array just an array of arrays, or, if one uses a fixed number of columns, is it just one logical contiguous array in memory? I don't actually plan to use mixed widths, it was just a strange test. But I want to make sure that Swift doesn't have to collate or do some other additional math to return rows when I want them. Commented Feb 12, 2016 at 19:48
  • @diatrevolo Thanks! I didn't think to explore the map function. Commented Feb 12, 2016 at 19:50
  • Ah, well an array in Swift, much like @EmilioPelaez mentioned, is a collection of objects, so it is much more akin to NSArray than float*. Commented Feb 12, 2016 at 19:50

1 Answer 1

3

How are Swift arrays different than c arrays

In C, an array is always a contiguous list of elements. In Swift, an array is a much more abstract data structure. You can make assumptions about how data is organized in memory with a C array, and you can even calculate the addresses of an element given the base address, element size, and an index. In Swift, not so much. Think of Swift's Array type the same way you think of NSArray in Objective-C. It's an ordered sequence of elements that provides array-like operations, but you shouldn't worry about how it stores the actual data.

I don't understand how it's possible to have a mixed row lengths is Swift.

Well, for one thing, you're really looking at an array of arrays. If an array is an object, then an array of arrays is probably implemented as an list of object pointers rather than a contiguous series of same-sized lists. You can do the same thing with NSArray, for example, because each item in an NSArray can be an object of any type.

So, is there some way to access an entire column in swift?

You'd need to iterate over the items in the array, which are themselves arrays, and examine the element at the "column" position you're interested in. I don't think there's a faster way to do it than that.

Sign up to request clarification or add additional context in comments.

1 Comment

Gotcha (and @EmilioPelaez and @diatrevolo). I was hoping that Swift arrays of primitives were more like native c arrays, from a performance standpoint. I can see the advantages of being able to fill and map these with more ease, as well as having the bounds protection. I just hope that there isn't too much of a performance hit when "sending" them to/from an Accelerate function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.