mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-28 12:05:41 +03:00
perf(at): Improve performance and compatibility with lodash (#798)
* perf(at): Improve performance and compatibility with lodash * Change the implementation to match `Array.prototype.at` implementation * Avoid truncating numbers if they are already integers
This commit is contained in:
parent
894a645c49
commit
c939d97322
@ -6,24 +6,35 @@ const atToolkit = atToolkit_;
|
|||||||
const atLodash = atLodash_;
|
const atLodash = atLodash_;
|
||||||
|
|
||||||
describe('at', () => {
|
describe('at', () => {
|
||||||
|
const data = ['a', 'b', 'c', 'd', 'e'];
|
||||||
|
const indices = [0, 2, -2, 1.5, -1.5];
|
||||||
|
|
||||||
bench('es-toolkit/at', () => {
|
bench('es-toolkit/at', () => {
|
||||||
atToolkit(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
|
atToolkit(data, indices);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench('lodash/at', () => {
|
bench('lodash/at', () => {
|
||||||
atLodash(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
|
atLodash(data, indices);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench('Array.prototype.at', () => {
|
||||||
|
indices.map(i => data.at(i));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('at/largeArray', () => {
|
describe('at/largeArray', () => {
|
||||||
const largeArray = Array.from({ length: 10000 }, (_, i) => i);
|
const largeData = Array.from({ length: 10000 }, (_, i) => i);
|
||||||
const largeIndex = Array.from({ length: 1000 }, (_, i) => i * 2);
|
const largeIndices = Array.from({ length: 1000 }, (_, i) => i * 2);
|
||||||
|
|
||||||
bench('es-toolkit/at', () => {
|
bench('es-toolkit/at', () => {
|
||||||
atToolkit(largeArray, largeIndex);
|
atToolkit(largeData, largeIndices);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench('lodash/at', () => {
|
bench('lodash/at', () => {
|
||||||
atLodash(largeArray, largeIndex);
|
atLodash(largeData, largeIndices);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench('Array.prototype.at', () => {
|
||||||
|
largeIndices.map(i => largeData.at(i));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -13,10 +13,17 @@ describe('at', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return `undefined` for nonexistent keys', () => {
|
it('should return `undefined` for nonexistent keys', () => {
|
||||||
expect(at(['a', 'b', 'c'], [2, 4, 0])).toEqual(['c', undefined, 'a']);
|
expect(at(['a', 'b', 'c'], [2, 4, 0, -4])).toEqual(['c', undefined, 'a', undefined]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an empty array when no keys are given', () => {
|
it('should return an empty array when no keys are given', () => {
|
||||||
expect(at(['a', 'b', 'c'], [])).toEqual([]);
|
expect(at(['a', 'b', 'c'], [])).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return undefined for non-integer indices', () => {
|
||||||
|
const data = ['a', 'b', 'c'];
|
||||||
|
const indices = [1.5, -1.5, NaN, Infinity, -Infinity];
|
||||||
|
|
||||||
|
expect(at(data, indices)).toEqual(indices.map(i => data.at(i)));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -14,12 +14,19 @@
|
|||||||
* console.log(result); // [20, 40, 50]
|
* console.log(result); // [20, 40, 50]
|
||||||
*/
|
*/
|
||||||
export function at<T>(arr: readonly T[], indices: number[]): Array<T | undefined> {
|
export function at<T>(arr: readonly T[], indices: number[]): Array<T | undefined> {
|
||||||
const result: Array<T | undefined> = new Array(indices.length);
|
const result = new Array<T | undefined>(indices.length);
|
||||||
|
const length = arr.length;
|
||||||
|
|
||||||
for (let i = 0; i < indices.length; i++) {
|
for (let i = 0; i < indices.length; i++) {
|
||||||
const index = indices[i];
|
let index = indices[i];
|
||||||
|
|
||||||
result[i] = arr.at(index);
|
index = Number.isInteger(index) ? index : Math.trunc(index) || 0;
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
index += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[i] = arr[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
Loading…
Reference in New Issue
Block a user