Skip to content

Commit

Permalink
feat(useArrayUnique): add a custom function to deduplicate (#2612)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alfred-Skyblue committed Mar 28, 2023
1 parent e81685a commit c8c3043
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 8 deletions.
18 changes: 18 additions & 0 deletions packages/shared/useArrayUnique/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,21 @@ const result = useArrayUnique(list)
list.push(1)
// result.value: [1, 2, 3]
```

### Use with custom function

```js
import { useArrayUnique } from '@vueuse/core'

const list = reactive([
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 1, name: 'baz' },
])

const result = useArrayUnique(list, (a, b) => a.id === b.id)
// result.value: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }]

list.push({ id: 1, name: 'qux' })
// result.value: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }]
```
22 changes: 16 additions & 6 deletions packages/shared/useArrayUnique/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,21 @@ describe('useArrayUnique', () => {
expect(result.value.length).toBe(3)
})

it('should work with reactive array', () => {
const list = reactive([1, 2, 2, 3])
const result = useArrayUnique(list)
expect(result.value.length).toBe(3)
list.push(1)
expect(result.value.length).toBe(3)
it('should work with array of reactive and custom compare function', () => {
const list = reactive([
{
id: 1,
name: 'foo',
}, {
id: 2,
name: 'bar',
},
{
id: 1,
name: 'baz',
},
])
const result = useArrayUnique(list, (a, b) => a.id === b.id)
expect(result.value.length).toBe(2)
})
})
23 changes: 21 additions & 2 deletions packages/shared/useArrayUnique/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@ import { computed } from 'vue-demi'
import type { MaybeComputedRef } from '../utils'
import { resolveUnref } from '../resolveUnref'

function uniq<T>(array: T[]) {
return Array.from(new Set(array))
}

function uniqueElementsBy<T>(
array: T[],
fn: (a: T, b: T, array: T[]) => boolean,
) {
return array.reduce<T[]>((acc, v) => {
if (!acc.some(x => fn(v, x, array)))
acc.push(v)
return acc
}, [])
}

/**
* reactive unique array
* @see https://vueuse.org/useArrayUnique
* @param {Array} list - the array was called upon.
* @param compareFn
* @returns {Array} A computed ref that returns a unique array of items.
*/
export function useArrayUnique<T>(
list: MaybeComputedRef<MaybeComputedRef<T>[]>): ComputedRef<T[]> {
return computed<T[]>(() => [...new Set<T>(resolveUnref(list).map(element => resolveUnref(element)))])
list: MaybeComputedRef<MaybeComputedRef<T>[]>, compareFn?: (a: T, b: T, array: T[]) => boolean): ComputedRef<T[]> {
return computed<T[]>(() => {
const resolvedList = resolveUnref(list).map(element => resolveUnref(element))
return compareFn ? uniqueElementsBy(resolvedList, compareFn) : uniq(resolvedList)
})
}

0 comments on commit c8c3043

Please sign in to comment.