mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-24 03:32:58 +03:00
feat(intersectionBy): Add intersectionBy
to compatibility layer (#721)
* feat(intersectionBy): Add `intersectionBy` to compatibility layer * test(intersectionBy): Add test case for array-like objects
This commit is contained in:
parent
4a8ea44edd
commit
4a1e410dd9
@ -1,8 +1,10 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
import { intersectionBy as intersectionByToolkit_ } from 'es-toolkit';
|
||||
import { intersectionBy as intersectionByCompatToolkit_ } from 'es-toolkit/compat';
|
||||
import { intersectionBy as intersectionByLodash_ } from 'lodash';
|
||||
|
||||
const intersectionByToolkit = intersectionByToolkit_;
|
||||
const intersectionByCompatToolkit = intersectionByCompatToolkit_;
|
||||
const intersectionByLodash = intersectionByLodash_;
|
||||
|
||||
describe('intersectionBy', () => {
|
||||
@ -13,6 +15,13 @@ describe('intersectionBy', () => {
|
||||
intersectionByToolkit(array1, array2, mapper);
|
||||
});
|
||||
|
||||
bench('es-toolkit/compat/intersectionBy', () => {
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
const mapper = item => item.id;
|
||||
intersectionByCompatToolkit(array1, array2, mapper);
|
||||
});
|
||||
|
||||
bench('lodash/intersectionBy', () => {
|
||||
const array1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
||||
const array2 = [{ id: 2 }, { id: 4 }];
|
||||
@ -30,6 +39,10 @@ describe('intersectionBy/largeArrays', () => {
|
||||
intersectionByToolkit(array1, array2, mapper);
|
||||
});
|
||||
|
||||
bench('es-toolkit/compat/intersectionBy', () => {
|
||||
intersectionByCompatToolkit(array1, array2, mapper);
|
||||
});
|
||||
|
||||
bench('lodash/intersectionBy', () => {
|
||||
intersectionByLodash(array1, array2, mapper);
|
||||
});
|
||||
|
@ -31,3 +31,30 @@ const mapper = item => item.id;
|
||||
const result = intersectionBy(array1, array2, mapper);
|
||||
// `mapper`で変換したとき、両方の配列に含まれる要素からなる [{ id: 2 }] 値が返されます。
|
||||
```
|
||||
|
||||
## Lodashとの互換性
|
||||
|
||||
`es-toolkit/compat`から`intersectionBy`をインポートすると、lodashと互換性があります。
|
||||
|
||||
- `intersectionBy`は共通要素を見つけるために複数の配列風オブジェクト(Array-like object)を受け入れます。
|
||||
- `intersectionBy`はプロパティキーをiterateeとして受け入れます。
|
||||
|
||||
```typescript
|
||||
import { intersectionBy } from 'es-toolkit/compat';
|
||||
|
||||
const array1 = [1.2, 2.4, 3.6];
|
||||
const array2 = [2.5, 3.7];
|
||||
const array3 = [2.6, 3.8];
|
||||
const result = intersectionBy(array1, array2, array3, Math.floor);
|
||||
// 結果は [2.4, 3.6] です。Math.floorを適用した後、共通要素は2と3です。
|
||||
|
||||
const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
const array2 = [{ x: 2 }, { x: 3 }, { x: 4 }];
|
||||
const result = intersectionBy(array1, array2, 'x');
|
||||
// 結果は [{ x: 2 }, { x: 3 }] です。これらの要素は同じ`x`プロパティを持っています。
|
||||
|
||||
const arrayLike1 = { 0: 'apple', 1: 'banana', 2: 'cherry', length: 3 };
|
||||
const arrayLike2 = { 0: 'banana', 1: 'cherry', 2: 'date', length: 3 };
|
||||
const result = intersectionBy(arrayLike1, arrayLike2);
|
||||
// 結果は ['banana', 'cherry'] です。これらの要素は両方の配列風オブジェクトに共通しています。
|
||||
```
|
||||
|
@ -31,3 +31,30 @@ const mapper = item => item.id;
|
||||
const result = intersectionBy(array1, array2, mapper);
|
||||
// `mapper`로 변환했을 때 두 배열 모두에 포함되는 요소로 이루어진 [{ id: 2 }] 값이 반환되어요.
|
||||
```
|
||||
|
||||
## Lodash와의 호환성
|
||||
|
||||
`es-toolkit/compat`에서 `intersectionBy`를 가져오면 lodash와 호환돼요.
|
||||
|
||||
- `intersectionBy`는 공통 요소를 찾기 위해 여러 개의 유사 배열 객체를 받을 수 있어요.
|
||||
- `intersectionBy`는 속성 키를 iteratee로 받을 수 있어요.
|
||||
|
||||
```typescript
|
||||
import { intersectionBy } from 'es-toolkit/compat';
|
||||
|
||||
const array1 = [1.2, 2.4, 3.6];
|
||||
const array2 = [2.5, 3.7];
|
||||
const array3 = [2.6, 3.8];
|
||||
const result = intersectionBy(array1, array2, array3, Math.floor);
|
||||
// 결과는 [2.4, 3.6]이에요. Math.floor를 적용한 후 공통 요소는 2와 3이에요.
|
||||
|
||||
const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
const array2 = [{ x: 2 }, { x: 3 }, { x: 4 }];
|
||||
const result = intersectionBy(array1, array2, 'x');
|
||||
// 결과는 [{ x: 2 }, { x: 3 }]이에요. 이 요소들은 동일한 `x` 속성을 가지고 있어요.
|
||||
|
||||
const arrayLike1 = { 0: 'apple', 1: 'banana', 2: 'cherry', length: 3 };
|
||||
const arrayLike2 = { 0: 'banana', 1: 'cherry', 2: 'date', length: 3 };
|
||||
const result = intersectionBy(arrayLike1, arrayLike2);
|
||||
// 결과는 ['banana', 'cherry']예요. 이 요소들은 두 유사 배열 객체에서 공통으로 존재해요.
|
||||
```
|
||||
|
@ -32,3 +32,30 @@ const mapper = item => item.id;
|
||||
const result = intersectionBy(array1, array2, mapper);
|
||||
// result will be [{ id: 2 }] since only this element has a matching id in both arrays.
|
||||
```
|
||||
|
||||
## Lodash Compatibility
|
||||
|
||||
Import `intersectionBy` from `es-toolkit/compat` for full compatibility with lodash.
|
||||
|
||||
- `intersectionBy` can accept multiple array-like objects to find common elements.
|
||||
- `intersectionBy` can accept a property key as the iteratee.
|
||||
|
||||
```typescript
|
||||
import { intersectionBy } from 'es-toolkit/compat';
|
||||
|
||||
const array1 = [1.2, 2.4, 3.6];
|
||||
const array2 = [2.5, 3.7];
|
||||
const array3 = [2.6, 3.8];
|
||||
const result = intersectionBy(array1, array2, array3, Math.floor);
|
||||
// result will be [2.4, 3.6] since the common elements after applying Math.floor are 2 and 3.
|
||||
|
||||
const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
const array2 = [{ x: 2 }, { x: 3 }, { x: 4 }];
|
||||
const result = intersectionBy(array1, array2, 'x');
|
||||
// result will be [{ x: 2 }, { x: 3 }] since these elements have the same `x` property.
|
||||
|
||||
const arrayLike1 = { 0: 'apple', 1: 'banana', 2: 'cherry', length: 3 };
|
||||
const arrayLike2 = { 0: 'banana', 1: 'cherry', 2: 'date', length: 3 };
|
||||
const result = intersectionBy(arrayLike1, arrayLike2);
|
||||
// result will be ['banana', 'cherry'] since these elements are common between the two array-like objects.
|
||||
```
|
||||
|
@ -31,3 +31,30 @@ const mapper = item => item.id;
|
||||
const result = intersectionBy(array1, array2, mapper);
|
||||
// 结果将是 [{ id: 2 }] 因为只有这个元素在两个数组中具有匹配的 id。
|
||||
```
|
||||
|
||||
## Lodash 兼容性
|
||||
|
||||
从 `es-toolkit/compat` 导入 `intersectionBy` 以获得与 lodash 的完全兼容性。
|
||||
|
||||
- `intersectionBy` 可以接受多个类数组对象来查找公共元素。
|
||||
- `intersectionBy` 可以将属性键作为迭代器使用。
|
||||
|
||||
```typescript
|
||||
import { intersectionBy } from 'es-toolkit/compat';
|
||||
|
||||
const array1 = [1.2, 2.4, 3.6];
|
||||
const array2 = [2.5, 3.7];
|
||||
const array3 = [2.6, 3.8];
|
||||
const result = intersectionBy(array1, array2, array3, Math.floor);
|
||||
// 结果是 [2.4, 3.6],因为在应用 Math.floor 之后,公共元素是2和3。
|
||||
|
||||
const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
const array2 = [{ x: 2 }, { x: 3 }, { x: 4 }];
|
||||
const result = intersectionBy(array1, array2, 'x');
|
||||
// 结果是 [{ x: 2 }, { x: 3 }],因为这些元素有相同的 `x` 属性。
|
||||
|
||||
const arrayLike1 = { 0: 'apple', 1: 'banana', 2: 'cherry', length: 3 };
|
||||
const arrayLike2 = { 0: 'banana', 1: 'cherry', 2: 'date', length: 3 };
|
||||
const result = intersectionBy(arrayLike1, arrayLike2);
|
||||
// 结果是 ['banana', 'cherry'],因为这些元素在两个类数组对象中都存在。
|
||||
```
|
||||
|
138
src/compat/array/intersectionBy.spec.ts
Normal file
138
src/compat/array/intersectionBy.spec.ts
Normal file
@ -0,0 +1,138 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { intersection } from './intersection';
|
||||
import { intersectionBy } from './intersectionBy';
|
||||
import { range } from '../../math';
|
||||
import { args } from '../_internal/args';
|
||||
import { LARGE_ARRAY_SIZE } from '../_internal/LARGE_ARRAY_SIZE';
|
||||
import { slice } from '../_internal/slice';
|
||||
import { stubNaN } from '../_internal/stubNaN';
|
||||
import { constant } from '../util/constant';
|
||||
import { times } from '../util/times';
|
||||
import { toString } from '../util/toString';
|
||||
|
||||
describe('intersectionBy', () => {
|
||||
/**
|
||||
* @see https://github.com/lodash/lodash/blob/afcd5bc1e8801867c31a17566e0e0edebb083d0e/test/intersection-methods.spec.js#L1
|
||||
*/
|
||||
it('should return the intersection of two arrays', () => {
|
||||
const actual = intersection([2, 1], [2, 3]);
|
||||
expect(actual).toEqual([2]);
|
||||
});
|
||||
|
||||
it('should return the intersection of multiple arrays', () => {
|
||||
const actual = intersection([2, 1, 2, 3], [3, 4], [3, 2]);
|
||||
expect(actual).toEqual([3]);
|
||||
});
|
||||
|
||||
it('should return an array of unique values', () => {
|
||||
const actual = intersection([1, 1, 3, 2, 2], [5, 2, 2, 1, 4], [2, 1, 1]);
|
||||
expect(actual).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it('should work with a single array', () => {
|
||||
const actual = intersection([1, 1, 3, 2, 2]);
|
||||
expect(actual).toEqual([1, 3, 2]);
|
||||
});
|
||||
|
||||
it('should work with `arguments` objects', () => {
|
||||
const array = [0, 1, null, 3];
|
||||
const expected = [1, 3];
|
||||
|
||||
expect(intersection(array, args)).toEqual(expected);
|
||||
expect(intersection(args, array)).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should treat `-0` as `0`', () => {
|
||||
const values = [-0, 0];
|
||||
const expected = values.map(constant(['0']));
|
||||
|
||||
const actual = values.map(value => intersection(values, [value]).map(toString));
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should match `NaN`', () => {
|
||||
const actual = intersection([1, NaN, 3], [NaN, 5, NaN]);
|
||||
expect(actual).toEqual([NaN]);
|
||||
});
|
||||
|
||||
it('should work with large arrays of `-0` as `0`', () => {
|
||||
const values = [-0, 0];
|
||||
const expected = values.map(constant(['0']));
|
||||
|
||||
const actual = values.map(value => {
|
||||
const largeArray = times(LARGE_ARRAY_SIZE, constant(value));
|
||||
return intersection(values, largeArray).map(toString);
|
||||
});
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should work with large arrays of `NaN`', () => {
|
||||
const largeArray = times(LARGE_ARRAY_SIZE, stubNaN);
|
||||
expect(intersection([1, NaN, 3], largeArray)).toEqual([NaN]);
|
||||
});
|
||||
|
||||
it('should work with large arrays of objects', () => {
|
||||
const object = {};
|
||||
const largeArray = times(LARGE_ARRAY_SIZE, constant(object));
|
||||
|
||||
expect(intersection([object], largeArray)).toEqual([object]);
|
||||
expect(intersection(range(LARGE_ARRAY_SIZE), [1])).toEqual([1]);
|
||||
});
|
||||
|
||||
it('should treat values that are not arrays or `arguments` objects as empty', () => {
|
||||
const array = [0, 1, null, 3];
|
||||
// @ts-ignore
|
||||
expect(intersection(array, 3, { 0: 1 }, null)).toEqual([]);
|
||||
expect(intersection(null, array, null, [2, 3])).toEqual([]);
|
||||
expect(intersection(array, null, args, null)).toEqual([]);
|
||||
});
|
||||
|
||||
/**
|
||||
* @see https://github.com/lodash/lodash/blob/afcd5bc1e8801867c31a17566e0e0edebb083d0e/test/intersectionBy.spec.js#L1
|
||||
*/
|
||||
it('should accept an `iteratee`', () => {
|
||||
const actual1 = intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
|
||||
expect(actual1).toEqual([2.1]);
|
||||
|
||||
const actual2 = intersectionBy([{ x: 1 }], [{ x: 2 }, { x: 1 }], 'x');
|
||||
expect(actual2).toEqual([{ x: 1 }]);
|
||||
|
||||
const actual3 = intersectionBy([2.1, 1.2], [2.3, 3.4], [1.2, 2.4], Math.floor);
|
||||
expect(actual3).toEqual([2.1]);
|
||||
|
||||
const actual4 = intersectionBy([1], [1], [1], [1], [1], [1], [1]);
|
||||
expect(actual4).toEqual([1]);
|
||||
});
|
||||
|
||||
it('should provide correct `iteratee` arguments', () => {
|
||||
let args: number[] | undefined;
|
||||
|
||||
intersectionBy([2.1, 1.2], [2.3, 3.4], function () {
|
||||
args || (args = slice.call(arguments));
|
||||
});
|
||||
|
||||
expect(args).toEqual([2.3]);
|
||||
});
|
||||
|
||||
it('should return empty array if no arrays provided', () => {
|
||||
expect(intersectionBy(null)).toEqual([]);
|
||||
expect(intersectionBy(undefined)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return as it is if only one array provided', () => {
|
||||
expect(intersectionBy([1, 2, 3])).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it('should return empty array if non array-like object is provided in the middle', () => {
|
||||
expect(intersectionBy([1, 2, 3], '123', [1, 2])).toEqual([]);
|
||||
});
|
||||
|
||||
it('should support array-like object', () => {
|
||||
expect(intersectionBy({ 0: 'a', 1: 'b', 2: 'c', length: 3 }, { 0: 'b', 1: 'c', length: 2 })).toEqual(['b', 'c']);
|
||||
expect(intersectionBy({ 0: 1.1, 1: 2.2, 2: 3.3, length: 3 }, { 0: 1.7, 1: 2.7, length: 2 }, Math.floor)).toEqual([
|
||||
1.1, 2.2,
|
||||
]);
|
||||
});
|
||||
});
|
197
src/compat/array/intersectionBy.ts
Normal file
197
src/compat/array/intersectionBy.ts
Normal file
@ -0,0 +1,197 @@
|
||||
import { intersectionBy as intersectionByToolkit } from '../../array/intersectionBy.ts';
|
||||
import { last } from '../../array/last.ts';
|
||||
import { uniq } from '../../array/uniq.ts';
|
||||
import { identity } from '../_internal/identity.ts';
|
||||
import { property } from '../object/property.ts';
|
||||
import { isArrayLikeObject } from '../predicate/isArrayLikeObject.ts';
|
||||
|
||||
/**
|
||||
* Returns the intersection of multiple arrays after applying the iteratee function to their elements.
|
||||
*
|
||||
* This function takes multiple arrays and an iteratee function (or property key) to
|
||||
* compare the elements after transforming them. It returns a new array containing the elements from
|
||||
* the first array that are present in all subsequent arrays after applying the iteratee to each element.
|
||||
*
|
||||
* @template T1, T2
|
||||
* @param {ArrayLike<T1> | null | undefined} array - The first array to compare.
|
||||
* @param {ArrayLike<T2>} values - The second array to compare.
|
||||
* @param {(value: T1 | T2) => unknown | string} iteratee - The iteratee invoked on each element
|
||||
* for comparison. It can also be a property key to compare based on that property.
|
||||
* @returns {T1[]} A new array containing the elements from the first array that are present
|
||||
* in all subsequent arrays after applying the iteratee.
|
||||
*
|
||||
* @example
|
||||
* const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
* const array2 = [{ x: 2 }, { x: 3 }, { x: 4 }];
|
||||
* const result = intersectionBy(array1, array2, 'x');
|
||||
* // result will be [{ x: 2 }, { x: 3 }] since these elements have the same `x` property.
|
||||
*
|
||||
* const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
* const array2 = [{ x: 2 }, { x: 3 }, { x: 4 }];
|
||||
* const result = intersectionBy(array1, array2, value => value.x);
|
||||
* // result will be [{ x: 2 }, { x: 3 }] since these elements have the same `x` property.
|
||||
*/
|
||||
export function intersectionBy<T1, T2>(
|
||||
array: ArrayLike<T1> | null | undefined,
|
||||
values: ArrayLike<T2>,
|
||||
iteratee: ((value: T1 | T2) => unknown) | string
|
||||
): T1[];
|
||||
|
||||
/**
|
||||
* Returns the intersection of multiple arrays after applying the iteratee function to their elements.
|
||||
*
|
||||
* This function takes multiple arrays and an iteratee function (or property key) to
|
||||
* compare the elements after transforming them. It returns a new array containing the elements from
|
||||
* the first array that are present in all subsequent arrays after applying the iteratee to each element.
|
||||
*
|
||||
* @template T1, T2, T3
|
||||
* @param {ArrayLike<T1> | null | undefined} array - The first array to compare.
|
||||
* @param {ArrayLike<T2>} values1 - The second array to compare.
|
||||
* @param {ArrayLike<T3>} values2 - The third array to compare.
|
||||
* @param {(value: T1 | T2 | T3) => unknown | string} iteratee - The iteratee invoked on each element
|
||||
* for comparison. It can also be a property key to compare based on that property.
|
||||
* @returns {T1[]} A new array containing the elements from the first array that are present
|
||||
* in all subsequent arrays after applying the iteratee.
|
||||
*
|
||||
* @example
|
||||
* const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
* const array2 = [{ x: 2 }, { x: 3 }];
|
||||
* const array3 = [{ x: 3 }];
|
||||
* const result = intersectionBy(array1, array2, array3, 'x');
|
||||
* // result will be [{ x: 3 }] since this element has the same `x` property in all arrays.
|
||||
*
|
||||
* const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
* const array2 = [{ x: 2 }, { x: 3 }];
|
||||
* const array3 = [{ x: 3 }];
|
||||
* const result = intersectionBy(array1, array2, array3, value => value.x);
|
||||
* // result will be [{ x: 3 }] since this element has the same `x` property in all arrays.
|
||||
*/
|
||||
export function intersectionBy<T1, T2, T3>(
|
||||
array: ArrayLike<T1> | null | undefined,
|
||||
values1: ArrayLike<T2>,
|
||||
values2: ArrayLike<T3>,
|
||||
iteratee: ((value: T1 | T2 | T3) => unknown) | string
|
||||
): T1[];
|
||||
|
||||
/**
|
||||
* Returns the intersection of multiple arrays after applying the iteratee function to their elements.
|
||||
*
|
||||
* This function takes multiple arrays and an iteratee function (or property key) to
|
||||
* compare the elements after transforming them. It returns a new array containing the elements from
|
||||
* the first array that are present in all subsequent arrays after applying the iteratee to each element.
|
||||
*
|
||||
* @template T1, T2, T3, T4
|
||||
* @param {ArrayLike<T1> | null | undefined} array - The first array to compare.
|
||||
* @param {ArrayLike<T2>} values1 - The second array to compare.
|
||||
* @param {ArrayLike<T3>} values2 - The third array to compare.
|
||||
* @param {...(ArrayLike<T4> | ((value: T1 | T2 | T3 | T4) => unknown) | string)} values - Additional arrays to compare, or the iteratee function.
|
||||
* @returns {T1[]} A new array containing the elements from the first array that are present
|
||||
* in all subsequent arrays after applying the iteratee.
|
||||
*
|
||||
* @example
|
||||
* const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
* const array2 = [{ x: 2 }, { x: 3 }];
|
||||
* const array3 = [{ x: 3 }];
|
||||
* const array4 = [{ x: 3 }, { x: 4 }];
|
||||
* const result = intersectionBy(array1, array2, array3, array4, 'x');
|
||||
* // result will be [{ x: 3 }] since this element has the same `x` property in all arrays.
|
||||
*
|
||||
* const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
* const array2 = [{ x: 2 }, { x: 3 }];
|
||||
* const array3 = [{ x: 3 }];
|
||||
* const array4 = [{ x: 3 }, { x: 4 }];
|
||||
* const result = intersectionBy(array1, array2, array3, array4, value => value.x);
|
||||
* // result will be [{ x: 3 }] since this element has the same `x` property in all arrays.
|
||||
*/
|
||||
export function intersectionBy<T1, T2, T3, T4>(
|
||||
array: ArrayLike<T1> | null | undefined,
|
||||
values1: ArrayLike<T2>,
|
||||
values2: ArrayLike<T3>,
|
||||
...values: Array<ArrayLike<T4> | ((value: T1 | T2 | T3 | T4) => unknown) | string>
|
||||
): T1[];
|
||||
|
||||
/**
|
||||
* Returns the intersection of multiple arrays after applying the iteratee function to their elements.
|
||||
*
|
||||
* This function takes multiple arrays and an iteratee function (or property key) to
|
||||
* compare the elements after transforming them. It returns a new array containing the elements from
|
||||
* the first array that are present in all subsequent arrays after applying the iteratee to each element.
|
||||
*
|
||||
* @template T
|
||||
* @param {ArrayLike<T> | null | undefined} [array] - The first array to compare.
|
||||
* @param {...ArrayLike<T>} values - Additional arrays to compare.
|
||||
* @returns {T[]} A new array containing the elements from the first array that are present
|
||||
* in all subsequent arrays after applying the iteratee.
|
||||
*
|
||||
* @example
|
||||
* const array1 = [1, 2, 3];
|
||||
* const array2 = [2, 3];
|
||||
* const array3 = [3];
|
||||
* const result = intersectionBy(array1, array2, array3);
|
||||
* // result will be [3] since these all elements have the same value 3.
|
||||
*/
|
||||
export function intersectionBy<T>(array?: ArrayLike<T> | null | undefined, ...values: Array<ArrayLike<T>>): T[];
|
||||
|
||||
/**
|
||||
* Returns the intersection of multiple arrays after applying the iteratee function to their elements.
|
||||
*
|
||||
* This function takes multiple arrays and an optional iteratee function (or property key)
|
||||
* to compare the elements after transforming them. It returns a new array containing the elements from
|
||||
* the first array that are present in all subsequent arrays after applying the iteratee to each element.
|
||||
* If no iteratee is provided, the identity function is used.
|
||||
*
|
||||
* If the first array is `null` or `undefined`, an empty array is returned.
|
||||
*
|
||||
* @template T
|
||||
* @param {ArrayLike<T> | null | undefined} array - The first array to compare.
|
||||
* @param {...(ArrayLike<T> | ((value: T) => unknown) | string)} values - The arrays to compare, or the iteratee function.
|
||||
* @returns {T[]} A new array containing the elements from the first array that are present
|
||||
* in all subsequent arrays after applying the iteratee.
|
||||
*
|
||||
* @example
|
||||
* const array1 = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
||||
* const array2 = [{ x: 2 }, { x: 3 }];
|
||||
* const result = intersectionBy(array1, array2, 'x');
|
||||
* // result will be [{ x: 2 }, { x: 3 }] since these elements have the same `x` property.
|
||||
*
|
||||
* @example
|
||||
* const array1 = [1.1, 2.2, 3.3];
|
||||
* const array2 = [2.3, 3.3];
|
||||
* const result = intersectionBy(array1, array2, Math.floor);
|
||||
* // result will be [2.3, 3.3] since it shares the same integer part when `Math.floor` is applied.
|
||||
*/
|
||||
export function intersectionBy<T>(
|
||||
array: ArrayLike<T> | null | undefined,
|
||||
...values: Array<ArrayLike<T> | ((value: T) => unknown) | string>
|
||||
): T[] {
|
||||
if (!isArrayLikeObject(array)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const lastValue = last(values);
|
||||
if (lastValue === undefined) {
|
||||
return Array.from(array);
|
||||
}
|
||||
|
||||
let result = uniq(Array.from(array));
|
||||
|
||||
const count = isArrayLikeObject(lastValue) ? values.length : values.length - 1;
|
||||
|
||||
for (let i = 0; i < count; ++i) {
|
||||
const value = values[i];
|
||||
|
||||
if (!isArrayLikeObject(value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (isArrayLikeObject(lastValue)) {
|
||||
result = intersectionByToolkit(result, Array.from(value), identity);
|
||||
} else if (typeof lastValue === 'function') {
|
||||
result = intersectionByToolkit(result, Array.from(value), value => lastValue(value));
|
||||
} else if (typeof lastValue === 'string') {
|
||||
result = intersectionByToolkit(result, Array.from(value), property(lastValue));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -47,6 +47,7 @@ export { head as first } from './array/head.ts';
|
||||
export { includes } from './array/includes.ts';
|
||||
export { indexOf } from './array/indexOf.ts';
|
||||
export { intersection } from './array/intersection.ts';
|
||||
export { intersectionBy } from './array/intersectionBy.ts';
|
||||
export { join } from './array/join.ts';
|
||||
export { last } from './array/last.ts';
|
||||
export { orderBy } from './array/orderBy.ts';
|
||||
|
Loading…
Reference in New Issue
Block a user