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_;
|
||||
|
||||
describe('at', () => {
|
||||
const data = ['a', 'b', 'c', 'd', 'e'];
|
||||
const indices = [0, 2, -2, 1.5, -1.5];
|
||||
|
||||
bench('es-toolkit/at', () => {
|
||||
atToolkit(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
|
||||
atToolkit(data, indices);
|
||||
});
|
||||
|
||||
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', () => {
|
||||
const largeArray = Array.from({ length: 10000 }, (_, i) => i);
|
||||
const largeIndex = Array.from({ length: 1000 }, (_, i) => i * 2);
|
||||
const largeData = Array.from({ length: 10000 }, (_, i) => i);
|
||||
const largeIndices = Array.from({ length: 1000 }, (_, i) => i * 2);
|
||||
|
||||
bench('es-toolkit/at', () => {
|
||||
atToolkit(largeArray, largeIndex);
|
||||
atToolkit(largeData, largeIndices);
|
||||
});
|
||||
|
||||
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', () => {
|
||||
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', () => {
|
||||
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]
|
||||
*/
|
||||
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++) {
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user