Skip to content

Commit 609dff2

Browse files
committed
fix: support negative indexing
1 parent 0e5a895 commit 609dff2

File tree

3 files changed

+89
-5
lines changed

3 files changed

+89
-5
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@dclimate/jaxray",
3-
"version": "0.6.0",
3+
"version": "0.6.1",
44
"description": "A javascript implementation similar to xarray",
55
"type": "module",
66
"main": "dist/index.js",

src/DataArray.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,18 +469,27 @@ export class DataArray {
469469

470470
/**
471471
* Select data by integer position
472+
* Supports negative indexing (Python-style): -1 = last, -2 = second-to-last, etc.
472473
*/
473474
async isel(selection: { [dimension: string]: number | number[] }): Promise<DataArray> {
474475
const indexSelection: Selection = {};
475476

476477
for (const [dim, sel] of Object.entries(selection)) {
478+
const coords = this._coords[dim];
479+
if (!coords) continue;
480+
477481
if (typeof sel === 'number') {
478-
// Convert index to coordinate value
479-
const coordValue = this._coords[dim]?.[sel];
482+
// Support negative indexing (Python-style: -1 = last, -2 = second-to-last, etc.)
483+
const index = sel < 0 ? coords.length + sel : sel;
484+
const coordValue = coords[index];
480485
indexSelection[dim] = coordValue;
481486
} else if (Array.isArray(sel)) {
482-
const coords = sel.map(i => this._coords[dim][i]);
483-
indexSelection[dim] = coords;
487+
// Support negative indexing in arrays
488+
const coordValues = sel.map(i => {
489+
const index = i < 0 ? coords.length + i : i;
490+
return coords[index];
491+
});
492+
indexSelection[dim] = coordValues;
484493
}
485494
}
486495

tests/DataArray.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,81 @@ describe('DataArray', () => {
9999
expect(selected.data).toBe(3);
100100
});
101101

102+
test('should support negative indexing in isel() for single values', async () => {
103+
const data = [10, 20, 30, 40, 50];
104+
const da = new DataArray(data, {
105+
dims: ['x'],
106+
coords: { x: [0, 1, 2, 3, 4] }
107+
});
108+
109+
// Select last element
110+
const last = await da.isel({ x: -1 });
111+
expect(last.data).toBe(50);
112+
113+
// Select second-to-last element
114+
const secondLast = await da.isel({ x: -2 });
115+
expect(secondLast.data).toBe(40);
116+
117+
// Select third-to-last element
118+
const thirdLast = await da.isel({ x: -3 });
119+
expect(thirdLast.data).toBe(30);
120+
121+
// First element (negative wrap around)
122+
const first = await da.isel({ x: -5 });
123+
expect(first.data).toBe(10);
124+
});
125+
126+
test('should support negative indexing in isel() for arrays', async () => {
127+
const data = [10, 20, 30, 40, 50];
128+
const da = new DataArray(data, {
129+
dims: ['x'],
130+
coords: { x: [0, 1, 2, 3, 4] }
131+
});
132+
133+
// Select first and last
134+
const edges = await da.isel({ x: [0, -1] });
135+
expect(edges.data).toEqual([10, 50]);
136+
137+
// Select last three elements
138+
const lastThree = await da.isel({ x: [-3, -2, -1] });
139+
expect(lastThree.data).toEqual([30, 40, 50]);
140+
141+
// Mix positive and negative indices
142+
const mixed = await da.isel({ x: [0, -2, 2] });
143+
expect(mixed.data).toEqual([10, 40, 30]);
144+
});
145+
146+
test('should support negative indexing in isel() for 2D arrays', async () => {
147+
const data = [
148+
[1, 2, 3],
149+
[4, 5, 6],
150+
[7, 8, 9]
151+
];
152+
const da = new DataArray(data, {
153+
dims: ['y', 'x'],
154+
coords: {
155+
y: [0, 1, 2],
156+
x: [0, 1, 2]
157+
}
158+
});
159+
160+
// Select last row
161+
const lastRow = await da.isel({ y: -1 });
162+
expect(lastRow.data).toEqual([7, 8, 9]);
163+
164+
// Select last column
165+
const lastCol = await da.isel({ x: -1 });
166+
expect(lastCol.data).toEqual([3, 6, 9]);
167+
168+
// Select bottom-right corner
169+
const corner = await da.isel({ y: -1, x: -1 });
170+
expect(corner.data).toBe(9);
171+
172+
// Select first row, last column
173+
const topRight = await da.isel({ y: 0, x: -1 });
174+
expect(topRight.data).toBe(3);
175+
});
176+
102177
test('should compute sum along dimension', () => {
103178
const data = [
104179
[1, 2, 3],

0 commit comments

Comments
 (0)