For the complete documentation index, see llms.txt. This page is also available as Markdown.

Indexing and Slicing

Accessing and modifying elements, rows, columns, and sub-arrays of INDArrays using NDArrayIndex

This page explains how to read and write individual values, rows, columns, and arbitrary sub-arrays of an INDArray. It also covers sequential iteration, tensor-along-dimension, boolean indexing, and converting NDArrays to plain Java arrays.

A note on views vs. copies

Many of the operations described on this page return a view, not a copy. A view is an INDArray that shares the same underlying off-heap memory as the original array. Mutations made through the view are immediately visible in the original, and vice-versa.

Operations that return views include getRow(), getColumn(), get(NDArrayIndex...) with NDArrayIndex.point(), .all(), or .interval(), tensorAlongDimension(), transpose(), and reshape().

Operations that return copies (new allocations) include getRows(int...), dup(), and toDoubleVector() / toDoubleMatrix().

When you need an independent copy of a view, call .dup() on the result:

INDArray rowCopy = myArray.getRow(0).dup(); // independent copy

1. Getting and Setting Individual Values

For an INDArray of rank N, you need N indices to address a single element. Indexing is zero-based: rows range from 0 to size(0)-1, columns from 0 to size(1)-1, and so on.

Performance note: Reading or writing one element at a time in a loop is expensive because each call crosses the JVM/off-heap boundary. Prefer bulk operations (ops, slices, assign()) whenever possible.

Reading single values

INDArray arr = Nd4j.create(new double[][]{
    {1.0, 2.0, 3.0},
    {4.0, 5.0, 6.0},
    {7.0, 8.0, 9.0}
});

// getDouble(int row, int col)  -- 2D shorthand
double val = arr.getDouble(1, 2);
// 6.0

// getDouble(int...)  -- works for any rank
double same = arr.getDouble(1, 2);
// 6.0

// getFloat / getInt -- same signatures, different return type
float f = arr.getFloat(0, 0);
// 1.0

int i = arr.getInt(2, 1);
// 8

For 3D or higher arrays supply three or more indices:

Writing single values: putScalar

Overloads also accept float and int values:


2. Row and Column Access

Getting rows

getRow(int) returns a view of a single row as a row vector:

Because row1 is a view, modifying it modifies arr as well:

To add to a row without keeping a reference, chain the call directly:

Getting multiple rows

getRows(int...) stacks the requested rows into a new matrix. This returns a copy, not a view:

Setting a row: putRow

Getting a column

getColumn(int) returns a view of a single column as a column vector:

Like getRow, this is a view -- writes to col0 affect arr.


3. NDArrayIndex-Based Access

The INDArray.get(NDArrayIndex...) family provides the most general sub-array access. You supply one NDArrayIndex per dimension; ND4J resolves which elements to include along each axis and returns a view of the result.

Import required:

NDArrayIndex.point(int)

Selects a single index along a dimension, collapsing that dimension:

NDArrayIndex.all()

Selects every index along a dimension (equivalent to : in NumPy):

NDArrayIndex.interval(int from, int to)

Selects indices [from, to) (inclusive start, exclusive end):

NDArrayIndex.interval(int from, int stride, int to)

Selects every stride-th index between from (inclusive) and to (exclusive):

NDArrayIndex.specified(long...)

Selects an explicit, possibly non-contiguous set of indices. This is the equivalent of fancy/advanced indexing:

Combining NDArrayIndex types

All four index types can be mixed freely across dimensions:

Extending to 1D arrays

For a 1D array (vector) provide a single NDArrayIndex:


4. Put Operations: Writing to Sub-Arrays

put(INDArrayIndex[], INDArray)

The counterpart to get -- writes the values of toPut into the sub-array identified by the index array:

The shape of patch must match the shape implied by the provided indices, or ND4J will throw.

Equivalence with get().assign()

Because get(NDArrayIndex...) returns a view, the two forms below are exactly equivalent:

Both overwrite the data in arr in place. Choose whichever reads more clearly.

Assigning a scalar to a slice

Combine get() and assign(double) to fill a region with a constant:


5. Tensor Along Dimension

Tensor Along Dimension (TAD) extracts a lower-rank sub-array from a higher-rank array. The result is always a view. TAD is particularly useful when you need to apply the same operation to every "slice" of an array along some set of dimensions.

Core method signatures

Note the double-s in tensorssAlongDimension -- that is the actual method name.

2D example

Shape rules for TAD

The shape of each returned tensor and the number of tensors are determined as follows:

Input shape
TAD dimensions
Number of tensors
Tensor shape

[a, b, c]

(0)

b * c

[1, a]

[a, b, c]

(1)

a * c

[1, b]

[a, b, c]

(0, 1)

c

[a, b]

[a, b, c]

(1, 2)

a

[b, c]

[a,b,c,d]

(1, 2)

a * d

[b, c]

[a,b,c,d]

(0, 2, 3)

b

[a, c, d]

3D example: iterating over 2D slices

Because TAD returns views, you can mutate each slice and the changes propagate back to volume.


6. Converting to Java Arrays

Sometimes you need a plain Java array for interoperability with existing code. ND4J provides several conversion methods. All of them allocate new Java heap arrays (copies, not views).

1D arrays

2D arrays

These methods only work for 1D and 2D arrays respectively. For higher-rank arrays, flatten first with ravel() or use getDouble(int[]) in a loop.


7. NdIndexIterator: Sequential Traversal

NdIndexIterator traverses all elements of an INDArray in C-order (row-major), producing the index tuple for each element in turn. The traversal order for a rank-2 array is [0,0], [0,1], ..., [0,n-1], [1,0], ....

For arrays with 3 or more dimensions, pass the full shape to the constructor:

NdIndexIterator is useful when you genuinely need to visit every element, for example to build a sparse representation or apply a predicate that cannot be vectorised. For most bulk operations, use ND4J ops instead.


8. Boolean Indexing

The BooleanIndexing class applies operations to elements of an array that satisfy a condition, without needing explicit index calculations.

Replace values that match a condition

Apply a value from a second array where condition holds

Available conditions

Factory method
Meaning

Conditions.lessThan(x)

element < x

Conditions.lessThanOrEqual(x)

element <= x

Conditions.greaterThan(x)

element > x

Conditions.greaterThanOrEqual(x)

element >= x

Conditions.equals(x)

element == x

Conditions.notEquals(x)

element != x

Conditions.isNan()

element is NaN

Conditions.isInfinite()

element is +/-Inf

Conditions.isFinite()

element is finite (not NaN, not Inf)

Conditions.absGreaterThan(x)

The full list and the unit tests for BooleanIndexing can be found in the BooleanIndexingTest source file.


9. Views in Depth: What Is and Is Not a View

Understanding whether an operation returns a view or a copy prevents subtle bugs.

Operations that return views

Modifying any of v1-v7 will modify a (and vice versa).

Operations that return copies

Forcing a copy

Call .dup() on any view to obtain an independent array:


Quick Reference

Goal
Method
Returns

Single element (double)

arr.getDouble(int, int)

double

Single element (float)

arr.getFloat(int)

float

Single element (any rank)

arr.getDouble(new int[]{i,j,k})

double

Write single element

arr.putScalar(new int[]{i,j}, v)

INDArray (this)

Whole row

arr.getRow(int)

VIEW

Multiple rows

arr.getRows(int...)

copy

Write a row

arr.putRow(int, INDArray)

INDArray (this)

Whole column

arr.getColumn(int)

VIEW

Point index

arr.get(NDArrayIndex.point(i), ...)

VIEW

Range

arr.get(NDArrayIndex.interval(a,b), ...)

VIEW

Strided range

arr.get(NDArrayIndex.interval(a,stride,b), ...)

VIEW

All elements on axis

arr.get(NDArrayIndex.all(), ...)

VIEW

Explicit indices

arr.get(NDArrayIndex.specified(0,2), ...)

VIEW

Write sub-array

arr.put(INDArrayIndex[], INDArray)

INDArray (this)

TAD count

arr.tensorssAlongDimension(int...)

long

TAD slice

arr.tensorAlongDimension(int, int...)

VIEW

Java double[]

arr.toDoubleVector()

copy

Java double[][]

arr.toDoubleMatrix()

copy

Java float[]

arr.toFloatVector()

copy

Sequential iteration

new NdIndexIterator(long...)

iterator

Boolean replace

BooleanIndexing.replaceWhere(arr, val, cond)

void (in-place)


See Also

Last updated

Was this helpful?