Skip to content

Commit 5b125ee

Browse files
committed
slice() function can get array as input
1 parent 0936c38 commit 5b125ee

File tree

6 files changed

+194
-7
lines changed

6 files changed

+194
-7
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const originalView = view(originalArray);
5555
originalView.subview(mask([true, false, true, false, true])).toArray(); // [1, 3, 5]
5656
originalView.subview(select([1, 2, 4])).toArray(); // [2, 3, 5]
5757
originalView.subview(slice('::-1')).toArray(); // [5, 4, 3, 2, 1]
58+
originalView.subview(slice([,,-1])).toArray(); // [5, 4, 3, 2, 1]
5859

5960
originalView.subview(mask([true, false, true, false, true])).apply((x: number) => x * 10);
6061
originalArray; // [10, 2, 30, 4, 50]

src/functions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function view<T>(source: Array<T> | ArrayViewInterface<T>, readonly?: boo
3333
*
3434
* This function allows you to create a selector for defining a subset of elements based on a slice range.
3535
*
36-
* @param {string | Slice} slice - The slice string or Slice object to create the selector from.
36+
* @param {string | Array<number | undefined> | Slice} slice - The slice string or Slice object to create the selector from.
3737
*
3838
* @returns {SliceSelector} The created SliceSelector instance.
3939
*
@@ -52,7 +52,7 @@ export function view<T>(source: Array<T> | ArrayViewInterface<T>, readonly?: boo
5252
* const slicedArray = view.loc[sliceSelector.toString()];
5353
* console.log(slicedArray);
5454
* // [2, 3, 4] */
55-
export function slice(slice: string | Slice): SliceSelector {
55+
export function slice(slice: string | Array<number | undefined> | Slice): SliceSelector {
5656
return new SliceSelector(Slice.toSlice(slice));
5757
}
5858

src/structs.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,23 @@ export class Slice {
2121
/**
2222
* Converts a slice string or Slice object into a Slice instance.
2323
*
24-
* @param {string | Slice} s - The slice string or Slice object to convert.
24+
* @param {string | Array<number | undefined> | Slice} s - The slice string/array or Slice object to convert.
2525
* @returns {Slice} The converted Slice instance.
2626
*/
27-
public static toSlice(s: string | Slice): Slice {
27+
public static toSlice(s: string | Array<number | undefined> | Slice): Slice {
2828
if (s instanceof Slice) {
2929
return s;
3030
}
3131

32+
if (Array.isArray(s) && this.isSliceArray(s)) {
33+
return new Slice(...(s as Array<number | undefined>));
34+
}
35+
3236
if (!this.isSliceString(s)) {
3337
throw new ValueError(`Invalid slice: "${String(s)}".`);
3438
}
3539

36-
const slice = this.parseSliceString(s);
40+
const slice = this.parseSliceString(s as string);
3741

3842
return new Slice(...slice);
3943
}
@@ -71,7 +75,32 @@ export class Slice {
7175

7276
const slice = this.parseSliceString(s);
7377

74-
return !(slice.length < 1 || slice.length > 3);
78+
return slice.length >= 1 && slice.length <= 3;
79+
}
80+
81+
/**
82+
* Checks if the provided value is a valid slice array.
83+
*
84+
* @param {unknown} s - The value to check.
85+
*
86+
* @returns {boolean} True if the value is a valid slice array, false otherwise.
87+
*/
88+
public static isSliceArray(s: unknown): boolean {
89+
if (!Array.isArray(s)) {
90+
return false;
91+
}
92+
93+
if(!(s.length >= 0 && s.length <= 3)) {
94+
return false;
95+
}
96+
97+
for (const item of s) {
98+
if (item !== undefined && !Number.isInteger(item)) {
99+
return false;
100+
}
101+
}
102+
103+
return true;
75104
}
76105

77106
/**

tests/examples/examples.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ it("Subview example", () => {
2929
expect(originalView.subview(mask([true, false, true, false, true])).toArray()).toEqual([1, 3, 5]);
3030
expect(originalView.subview(select([1, 2, 4])).toArray()).toEqual([2, 3, 5]);
3131
expect(originalView.subview(slice('::-1')).toArray()).toEqual([5, 4, 3, 2, 1]);
32+
expect(originalView.subview(slice([,,-1])).toArray()).toEqual([5, 4, 3, 2, 1]);
3233

3334
originalView.subview(mask([true, false, true, false, true])).apply((x: number) => x * 10);
3435
expect(originalArray).toEqual([10, 2, 30, 4, 50]);

tests/structs/slice.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,67 @@ function dataProviderForNormalize(): Array<unknown> {
226226
[':3:-1', 10, '9:3:-1', [9, 8, 7, 6, 5, 4]],
227227
];
228228
}
229+
230+
describe.each([
231+
...dataProviderForIsSliceArrayTrue(),
232+
] as Array<[Array<number>]>)(
233+
"Is Slice Array",
234+
(input: Array<number>) => {
235+
it("", () => {
236+
expect(Slice.isSliceArray(input)).toBeTruthy();
237+
});
238+
},
239+
);
240+
241+
function dataProviderForIsSliceArrayTrue(): Array<unknown> {
242+
return [
243+
[[]],
244+
[[,]],
245+
[[,,]],
246+
[[0]],
247+
[[0,]],
248+
[[0,,]],
249+
[[1,,]],
250+
[[1,0,]],
251+
[[1,1,]],
252+
[[-1,1,]],
253+
[[1,,1]],
254+
[[1,,2]],
255+
[[,,1]],
256+
[[,,-1]],
257+
[[1,10,-1]],
258+
];
259+
}
260+
261+
describe.each([
262+
...dataProviderForIsSliceArrayFalse(),
263+
] as Array<[Array<number>]>)(
264+
"Is Slice Array",
265+
(input: Array<number>) => {
266+
it("", () => {
267+
expect(Slice.isSliceArray(input)).toBeFalsy();
268+
});
269+
},
270+
);
271+
272+
function dataProviderForIsSliceArrayFalse(): Array<unknown> {
273+
return [
274+
[['']],
275+
[['a']],
276+
[[0, 1, 'a']],
277+
[[0, 1, 2, 3]],
278+
[[1.1, 1, 2]],
279+
[[1, 1, 2.2]],
280+
[null],
281+
[0],
282+
[1],
283+
[0.0],
284+
[1.0],
285+
[true],
286+
[false],
287+
[{}],
288+
[{a: 1}],
289+
[[{}]],
290+
[[{a: 1}]],
291+
];
292+
}

tests/views/slice-view.test.ts

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
dataProviderForSliceOutOfBoundsPythonAutoGenerated,
44
// @ts-ignore
55
} from "../fixtures/python-slices";
6-
import { view } from "../../src";
6+
import { slice, view } from "../../src";
77

88
describe.each([
99
...dataProviderForSliceSubviewRead(),
@@ -76,6 +76,40 @@ describe.each([
7676
},
7777
);
7878

79+
80+
describe.each([
81+
...dataProviderForSliceSubviewRead(),
82+
...dataProviderForSliceArraySubviewRead(),
83+
] as Array<[Array<number>, string | Array<number | undefined>, Array<number>]>)(
84+
"Array View Slice Array Subview Loc Read Test",
85+
(
86+
source: Array<number>,
87+
config: string | Array<number | undefined>,
88+
expected: Array<number>,
89+
) => {
90+
it("", () => {
91+
// Given
92+
const v = view(source);
93+
const slicedArray = v.subview(slice(config)).loc[':'];
94+
95+
expect(slicedArray).toEqual(expected);
96+
expect(slicedArray.length).toEqual(expected.length);
97+
98+
for (let i = 0; i < slicedArray.length; i++) {
99+
expect(slicedArray[i]).toBe(expected[i]);
100+
}
101+
102+
for (let i = 0; i < v.length; i++) {
103+
expect(v.loc[i]).toBe(source[i]);
104+
}
105+
106+
// And then
107+
expect(v.toArray()).toEqual(source);
108+
expect(slicedArray).toEqual(expected);
109+
});
110+
},
111+
);
112+
79113
function dataProviderForSliceSubviewRead(): Array<unknown> {
80114
return [
81115
[[1, 2, 3, 4, 5, 6, 7, 8, 9], '1:6', [2, 3, 4, 5, 6]],
@@ -129,6 +163,17 @@ function dataProviderForSliceSubviewRead(): Array<unknown> {
129163
];
130164
}
131165

166+
function dataProviderForSliceArraySubviewRead(): Array<unknown> {
167+
return [
168+
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [1,6], [2, 3, 4, 5, 6]],
169+
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [1,6,1], [2, 3, 4, 5, 6]],
170+
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [1,6,2], [2, 4, 6]],
171+
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [2,8], [3, 4, 5, 6, 7, 8]],
172+
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [2,8,1], [3, 4, 5, 6, 7, 8]],
173+
[[1, 2, 3, 4, 5, 6, 7, 8, 9], [2,8,2], [3, 5, 7]],
174+
];
175+
}
176+
132177
describe.each([
133178
...dataProviderForSliceSubviewWrite(),
134179
] as Array<[Array<number>, string, Array<number>, Array<number>]>)(
@@ -153,6 +198,31 @@ describe.each([
153198
},
154199
);
155200

201+
describe.each([
202+
...dataProviderForSliceSubviewWrite(),
203+
...dataProviderForSliceArraySubviewWrite(),
204+
] as Array<[Array<number>, string | Array<number | undefined>, Array<number>, Array<number>]>)(
205+
"Array View Slice Subview Loc Write Test",
206+
(
207+
source: Array<number>,
208+
config: string | Array<number | undefined>,
209+
toWrite: Array<number>,
210+
expected: Array<number>,
211+
) => {
212+
it("", () => {
213+
// Given
214+
const v = view(source);
215+
216+
// When
217+
v.subview(slice(config)).loc[':'] = toWrite;
218+
219+
// And then
220+
expect(v.toArray()).toEqual(expected);
221+
expect(source).toEqual(expected);
222+
});
223+
},
224+
);
225+
156226
function dataProviderForSliceSubviewWrite(): Array<unknown> {
157227
return [
158228
[[], ':', [], []],
@@ -173,3 +243,25 @@ function dataProviderForSliceSubviewWrite(): Array<unknown> {
173243
[[1, 2, 3, 4, 5, 6, 7, 8], '1:-1:2', [77, 88, 99], [1, 77, 3, 88, 5, 99, 7, 8]],
174244
];
175245
}
246+
247+
function dataProviderForSliceArraySubviewWrite(): Array<unknown> {
248+
return [
249+
[[], [], [], []],
250+
[[], [,], [], []],
251+
[[1], [,], [11], [11]],
252+
[[1, 2, 3], [,], [2, 4, 6], [2, 4, 6]],
253+
[[1, 2, 3], [0,], [2, 4, 6], [2, 4, 6]],
254+
[[1, 2, 3], [0,3], [2, 4, 6], [2, 4, 6]],
255+
[[1, 2, 3], [0,3], [2, 4, 6], [2, 4, 6]],
256+
[[1, 2, 3], [1,], [22, 33], [1, 22, 33]],
257+
[[1, 2, 3], [,2], [11, 22], [11, 22, 3]],
258+
[[1, 2, 3], [,-1], [11, 22], [11, 22, 3]],
259+
[[1, 2, 3, 4, 5, 6], [,,2], [77, 88, 99], [77, 2, 88, 4, 99, 6]],
260+
[[1, 2, 3, 4, 5, 6], [,,-2], [77, 88, 99], [1, 99, 3, 88, 5, 77]],
261+
[[1, 2, 3, 4, 5, 6], [1,,2], [77, 88, 99], [1, 77, 3, 88, 5, 99]],
262+
[[1, 2, 3, 4, 5, 6], [-2,,-2], [77, 88, 99], [99, 2, 88, 4, 77, 6]],
263+
[[1, 2, 3, 4, 5, 6, 7, 8], [,-2,2], [77, 88, 99], [77, 2, 88, 4, 99, 6, 7, 8]],
264+
[[1, 2, 3, 4, 5, 6, 7, 8], [,6,2], [77, 88, 99], [77, 2, 88, 4, 99, 6, 7, 8]],
265+
[[1, 2, 3, 4, 5, 6, 7, 8], [1,-1,2], [77, 88, 99], [1, 77, 3, 88, 5, 99, 7, 8]],
266+
];
267+
}

0 commit comments

Comments
 (0)