Skip to content

Commit

Permalink
feat: xor, xorWith
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Nov 14, 2024
1 parent 1fd7d03 commit d732521
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 4 deletions.
2 changes: 2 additions & 0 deletions docs/.vitepress/items/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export const arrayItems = [
{ text: 'differenceWith', link: '/array/difference-with' },
{ text: 'intersection', link: '/array/intersection' },
{ text: 'intersectionWith', link: '/array/intersection-with' },
{ text: 'xor', link: '/array/xor' },
{ text: 'xorWith', link: '/array/xor-with' },
{ text: 'groupBy', link: '/array/group-by' },
{ text: 'find', link: '/array/find' },
{ text: 'shuffle', link: '/array/shuffle' },
Expand Down
2 changes: 1 addition & 1 deletion docs/array/difference-with.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Creates an `array` of array values ​​that are not contained in other given a
### Usage

```ts
import { difference } from 'rattail'
import { differenceWith } from 'rattail'

differenceWith([{ num: 1 }, { num: 2 }, { num: 3 }], [{ num: 2 }], (a, b) => a.num === b.num)
// return [{ num: 1 }, { num: 3 }]
Expand Down
27 changes: 27 additions & 0 deletions docs/array/xor-with.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# xorWith

XOR(Exclusive OR) the passed array and return a new `array`, and supports custom comparison functions.

### Usage

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

xorWith([{ num: 1 }, { num: 2 }, { num: 2 }], [{ num: 1 }, { num: 3 }], (a, b) => a.num === b.num)
// return [{ num: 2 }, { num: 3 }]
xorWith([{ num: 1 }, { num: 2 }], [{ num: 1 }, { num: 2 }], [{ num: 3 }], (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/xor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# xor

XOR(Exclusive OR) the passed array and return a new `array`.

### Usage

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

xor([1, 2, 2], [1, 3])
// return [2, 3]
xor([1, 2], [1, 2], [3])
// return [3]
```

### Arguments

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

### Return

| Type |
| ------- |
| `Array` |
2 changes: 1 addition & 1 deletion docs/zh/array/difference-with.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
### 使用

```ts
import { difference } from 'rattail'
import { differenceWith } from 'rattail'

differenceWith([{ num: 1 }, { num: 2 }, { num: 3 }], [{ num: 2 }], (a, b) => a.num === b.num)
// return [{ num: 1 }, { num: 3 }]
Expand Down
27 changes: 27 additions & 0 deletions docs/zh/array/xor-with.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# xorWith

对传入的数组进行异或(Exclusive OR)计算,返回一个新的 `数组`,并支持自定义比较函数。

### 使用

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

xorWith([{ num: 1 }, { num: 2 }, { num: 2 }], [{ num: 1 }, { num: 3 }], (a, b) => a.num === b.num)
// return [{ num: 2 }, { num: 3 }]
xorWith([{ num: 1 }, { num: 2 }], [{ num: 1 }, { num: 2 }], [{ num: 3 }], (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/xor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# xor

对传入的数组进行异或(Exclusive OR)计算,返回一个新的 `数组`

### 使用

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

xor([1, 2, 2], [1, 3])
// return [2, 3]
xor([1, 2], [1, 2], [3])
// return [3]
```

### 参数

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

### 返回值

| 类型 |
| ------- |
| `Array` |
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@
},
"scripts": {
"prepare": "simple-git-hooks",
"dev": "tsup src/index.ts --format esm --out-dir=lib --watch --dts",
"dev": "vitest --coverage",
"build": "tsup src/index.ts --format esm,cjs --out-dir=lib --dts --clean",
"lint": "eslint . --fix --ext .ts,.js",
"format": "prettier --write .",
"clean": "rimraf node_modules lib",
"test:watch": "vitest --coverage",
"test": "vitest run --coverage",
"release": "pnpm build && vr release",
"docs:dev": "vitepress dev docs",
Expand Down
2 changes: 2 additions & 0 deletions src/array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ export * from './differenceWith'
export * from './intersection'
export * from './intersectionWith'
export * from './groupBy'
export * from './xor'
export * from './xorWith'
5 changes: 5 additions & 0 deletions src/array/xor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { xorWith } from './xorWith'

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

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

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

return uniqBy(
targets.reduce((result, target) => {
return [...differenceWith(result, target, fn), ...differenceWith(target, result, fn)]
}),
fn,
)
}
21 changes: 21 additions & 0 deletions tests/array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
intersection,
intersectionWith,
groupBy,
xor,
xorWith,
} from '../src'

it('uniq', () => {
Expand Down Expand Up @@ -183,3 +185,22 @@ it('groupBy', () => {
male: [{ name: 'c', gender: 'male' }],
})
})

it('xor', () => {
expect(xor([])).toEqual([])
expect(xor([1, 2])).toEqual([1, 2])
expect(xor([1, 2], [1, 2], [3])).toEqual([3])
expect(xor([1, 2, 2], [1, 3])).toEqual([2, 3])
expect(xor([], [1, 3])).toEqual([1, 3])
expect(xor([1, 3], [])).toEqual([1, 3])
})

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

0 comments on commit d732521

Please sign in to comment.