I'd need to reduce a huge intArray to an array of ...
# getting-started
e
I'd need to reduce a huge intArray to an array of 3-items intarrays, is there a way to do that using the stdlib instead of a plain
Array(size) { IntArray(3) {..}}
constructor?
s
Since you're working with arrays, a lot of the stdlib functions aren't available. You could do
ints.asList().chunked(3)
, but you'll get back a
List<List<Int>>
. If you actually need an
Array<IntArray>
, it's probably more efficient to do it the way you initially described.
👍 1
y
Do you actually need arrays though? Lists are nice because they're an interface, so you can easily build views on them. For instance,
ints.asList().chunked(3) { ... }
Only actually creates one extra list, not n/3, because the passed in list is a view on the original list and that view is ephemeral, meaning that the caller shouldn't keep it around, thus the view gets mutated after every call to refer to the next chunk
e
I'd like to be as fast as possible, arrays should be the most efficient structure to hold data
f
In that case, why not iterate through the original array in steps of 3? Saves you the trouble of allocating and populating all these extra arrays.
y
Sure, but you do realise Lists et al use arrays under the hood right? In fact,
ints.asList()
is a super basic wrapper around an array. Allocating new arrays is IMO unnecessary if you can instead use lists as views into it
m
IntArray
do not require the
Int
to be boxed unlike
List<Int>
, so if the list is large that can have a performance and memory impact.
y
Oh that's true. Sorry I forgot about primitives Sure then you can make an
IntList
interface and basically recreate the stdlib chunked logic to have views on your new interface
k
If you're looking for absolute maximum possible efficiency (e.g. if you're doing high-frequency trading), keep in mind that an
Array<IntArray>
is still an array of references to 3-element int arrays. You will probably lose the advantage of cache locality. What you really want is a 2D IntArray, such as those supported by C#, which are represented as a contiguous 1D array but
a[n, m]
is syntactic sugar for
a[n * (size of 1st dimension) + m]
. Unfortunately, Kotlin doesn't support 2D arrays (only arrays of arrays, which are a cheap imitation) but you can use a small function to do your indexing arithmetic and the JIT will almost certainly inline it.
e
that's also what I assumed, thanks for the tip!
m
You could even overload the
get
operator to take two arguments.
private operator fun IntArray.get(row: Int, column: Int): Int = get(row * 3 + column)
. An inline class could be created to support a 2D int array for general use.
👍 2