Skip to content

Commit

Permalink
feat: intersection, intersectionWith
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Nov 12, 2024
1 parent 2b73553 commit c8597e2
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 15 deletions.
2 changes: 2 additions & 0 deletions docs/.vitepress/items/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export const arrayItems = [
{ text: 'uniqBy', link: '/array/uniq-by' },
{ text: 'difference', link: '/array/difference' },
{ text: 'differenceWith', link: '/array/difference-with' },
{ text: 'intersection', link: '/array/intersection' },
{ text: 'intersectionWith', link: '/array/intersection-with' },
{ text: 'find', link: '/array/find' },
{ text: 'shuffle', link: '/array/shuffle' },
{ text: 'removeItem', link: '/array/remove-item' },
Expand Down
36 changes: 36 additions & 0 deletions docs/array/intersection-with.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# intersectionWith

Creates an `array` of unique values ​​contained in all given arrays, and supports custom comparison functions.

### Usage

```ts
import { intersectionWith } from 'rattail'

intersectionWith(
[{ num: 1 }, { num: 2 }, { num: 3 }, { num: 3 }],
[{ num: 2 }, { num: 3 }, { num: 4 }],
(a, b) => a.num === b.num,
)
// return [{ num: 2 }, { num: 3 }]
intersectionWith(
[{ num: 1 }, { num: 2 }, { num: 3 }, { num: 3 }],
[{ num: 2 }, { num: 3 }, { num: 4 }],
[{ num: 3 }, { num: 4 }, { num: 5 }],
(a, b) => a.num === b.num,
)
// return [{ num: 3 }]
```

### Arguments

| Arg | Type | Defaults |
| ----------- | ------------------------- | -------- |
| `...values` | `Array<Array>` | |
| `fn` | `(a: any, b: any) => any` | |

### Return

| Type |
| ------- |
| `Array` |
26 changes: 26 additions & 0 deletions docs/array/intersection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# intersection

Creates an `array` of unique values ​​contained in all given arrays.

### Usage

```ts
import { intersection } from 'rattail'

intersection([1, 2, 3, 3], [2, 3, 4])
// return [2, 3]
intersection([1, 2, 3, 3], [2, 3, 4], [3, 4, 5])
// return [3]
```

### Arguments

| Arg | Type | Defaults |
| ----------- | -------------- | -------- |
| `...values` | `Array<Array>` | |

### Return

| Type |
| ------- |
| `Array` |
36 changes: 36 additions & 0 deletions docs/zh/array/intersection-with.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# intersectionWith

创建一个去重数组,数组中的每个值都被包含在所有的给定数组中(数组取交集),支持传入比较函数。

### 使用

```ts
import { intersectionWith } from 'rattail'

intersectionWith(
[{ num: 1 }, { num: 2 }, { num: 3 }, { num: 3 }],
[{ num: 2 }, { num: 3 }, { num: 4 }],
(a, b) => a.num === b.num,
)
// return [{ num: 2 }, { num: 3 }]
intersectionWith(
[{ num: 1 }, { num: 2 }, { num: 3 }, { num: 3 }],
[{ num: 2 }, { num: 3 }, { num: 4 }],
[{ num: 3 }, { num: 4 }, { num: 5 }],
(a, b) => a.num === b.num,
)
// return [{ num: 3 }]
```

### 参数

| 参数 | 类型 | 默认值 |
| ----------- | ------------------------- | ------ |
| `...values` | `Array<Array>` | |
| `fn` | `(a: any, b: any) => any` | |

### 返回值

| 类型 |
| ------- |
| `Array` |
26 changes: 26 additions & 0 deletions docs/zh/array/intersection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# intersection

创建一个去重数组,数组中的每个值都被包含在所有的给定数组中(数组取交集)。

### 使用

```ts
import { intersection } from 'rattail'

intersection([1, 2, 3, 3], [2, 3, 4])
// return [2, 3]
intersection([1, 2, 3, 3], [2, 3, 4], [3, 4, 5])
// return [3]
```

### 参数

| 参数 | 类型 | 默认值 |
| ----------- | -------------- | ------ |
| `...values` | `Array<Array>` | |

### 返回值

| 类型 |
| ------- |
| `Array` |
2 changes: 2 additions & 0 deletions src/array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export * from './removeArrayEmpty'
export * from './normalizeToArray'
export * from './difference'
export * from './differenceWith'
export * from './intersection'
export * from './intersectionWith'
5 changes: 5 additions & 0 deletions src/array/intersection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { intersectionWith } from './intersectionWith'

export function intersection<T>(...values: T[][]): T[] {
return intersectionWith(...values, (a, b) => a === b)
}
26 changes: 26 additions & 0 deletions src/array/intersectionWith.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { at } from './at'
import { uniqBy } from './uniqBy'

type Fn<T> = (a: T, b: T) => any

export function intersectionWith<T>(...values: [...T[][], fn: Fn<T>]): T[] {
const fn = at(values, -1) as Fn<T>
const targets = values.slice(0, -1) as T[][]

if (targets.length === 0) {
return []
}

if (targets.length === 1) {
return uniqBy(targets[0], fn)
}

function baseIntersectionWith(arr1: T[], arr2: T[]): T[] {
return arr1.filter((item) => arr2.some((value) => fn(item, value)))
}

return uniqBy(
targets.reduce((result, target) => baseIntersectionWith(result, target)),
fn,
)
}
71 changes: 56 additions & 15 deletions tests/array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
chunk,
difference,
differenceWith,
intersection,
intersectionWith,
} from '../src'

it('uniq', () => {
Expand Down Expand Up @@ -98,22 +100,61 @@ it('chunk', () => {
})

it('difference', () => {
expect(difference([1, 2, 3, 4])).toEqual([1, 2, 3, 4])
expect(difference([1, 2, 3, 4], [2, 3])).toEqual([1, 4])
expect(difference([1, 2, 3, 4], [2, 3], [3, 4])).toEqual([1])
const a = [1, 2, 3, 4]
expect(difference(a)).toEqual([1, 2, 3, 4])
expect(difference(a)).not.toBe(a)

const b = [1, 2, 3, 4]
expect(difference(b, [2, 3])).toEqual([1, 4])
expect(difference(b, [2, 3])).not.toBe(b)

const c = [1, 2, 3, 4]
expect(difference(c, [2, 3], [3, 4])).toEqual([1])
expect(difference(c, [2, 3], [3, 4])).not.toBe(c)
})

it('differenceWith', () => {
expect(differenceWith([{ num: 1 }, { num: 2 }, { num: 3 }], (a, b) => a.num === b.num)).toEqual([
{ num: 1 },
{ num: 2 },
{ num: 3 },
])
expect(differenceWith([{ num: 1 }, { num: 2 }, { num: 3 }], [{ num: 2 }], (a, b) => a.num === b.num)).toEqual([
{ num: 1 },
{ num: 3 },
])
expect(
differenceWith([{ num: 1 }, { num: 2 }, { num: 3 }], [{ num: 2 }], [{ num: 3 }], (a, b) => a.num === b.num),
).toEqual([{ num: 1 }])
const a = [{ num: 1 }, { num: 2 }, { num: 3 }]
expect(differenceWith(a, (a, b) => a.num === b.num)).toEqual([{ num: 1 }, { num: 2 }, { num: 3 }])
expect(differenceWith(a, (a, b) => a.num === b.num)).not.toBe(a)

const b = [{ num: 1 }, { num: 2 }, { num: 3 }]
expect(differenceWith(b, [{ num: 2 }], (a, b) => a.num === b.num)).toEqual([{ num: 1 }, { num: 3 }])
expect(differenceWith(b, [{ num: 2 }], (a, b) => a.num === b.num)).not.toBe(b)

const c = [{ num: 1 }, { num: 2 }, { num: 3 }]
expect(differenceWith(c, [{ num: 2 }], [{ num: 3 }], (a, b) => a.num === b.num)).toEqual([{ num: 1 }])
expect(differenceWith(c, [{ num: 2 }], [{ num: 3 }], (a, b) => a.num === b.num)).not.toBe(c)
})

it('intersection', () => {
expect(intersection()).toEqual([])

const a = [1, 2, 3, 3]
expect(intersection(a)).toEqual([1, 2, 3])
expect(intersection(a)).not.toBe(a)

const b = [1, 2, 3, 3]
expect(intersection(b, [2, 3, 4])).toEqual([2, 3])
expect(intersection(b, [2, 3, 4])).not.toBe(b)

const c = [1, 2, 3, 3]
expect(intersection(c, [2, 3, 4], [3, 4, 5])).toEqual([3])
expect(intersection(c, [2, 3, 4], [3, 4, 5])).not.toBe(c)
})

it('intersectionWith', () => {
expect(intersectionWith((a, b) => a === b)).toEqual([])

const a = [{ num: 1 }, { num: 2 }, { num: 3 }, { num: 3 }]
expect(intersectionWith(a, (a, b) => a.num === b.num)).toEqual([{ num: 1 }, { num: 2 }, { num: 3 }])
expect(intersectionWith(a, (a, b) => a.num === b.num)).not.toBe(a)

const b = [{ num: 1 }, { num: 2 }, { num: 3 }, { num: 3 }]
expect(intersectionWith(b, [{ num: 2 }], (a, b) => a.num === b.num)).toEqual([{ num: 2 }])
expect(intersectionWith(b, [{ num: 2 }], (a, b) => a.num === b.num)).not.toBe(b)

const c = [{ num: 1 }, { num: 2 }, { num: 3 }, { num: 3 }]
expect(intersectionWith(c, [{ num: 2 }], [{ num: 3 }], (a, b) => a.num === b.num)).toEqual([])
expect(intersectionWith(c, [{ num: 2 }], [{ num: 3 }], (a, b) => a.num === b.num)).not.toBe(c)
})

0 comments on commit c8597e2

Please sign in to comment.