點燈坊

學而時習之,不亦悅乎

使用 uniqBy() 經過轉換後再取得不重複 Array

Sam Xiao's Avatar 2019-07-07

對於一般需求,uniq() 即可勝任,但若需經過 Function 轉換後才比較,則要使用 uniqBy(),自行傳入 Callback。

Version

macOS Mojave 10.14.5
VS Code 1.33.1
Quokka 1.0.212
Ramda 0.26.1

Functional

import { uniqBy, identity } from 'ramda';

let data = [1, 2, 3, 1];

uniqBy(identity)(data); // ? 

data 很明顯 1 是重複的,我們希望結果只顯示 [1, 2, 3]

若我們不知道 uniq(),也可以使用 uniqBy()identity() 組合而成。

uniqBy()
(a -> b) -> [a] -> [a]
將 array 經過 supply function 轉換,回傳 element 不重複 array

(a -> b):supply function,先經過轉換後再比較

[a]:data 為 array

[a]:回傳 element 不重複 array

事實上 Ramda 的 uniq() 就是由 uniqBy(identity) 實現

uniqby002

Ramda

import { uniq } from 'ramda';

let data = [1, 2, 3, 1];

uniq(data); // ?

事實上 Ramda 已經提供 uniq(),可直接使用。

uniq()
[a] -> [a]
回傳 element 不重複 array

uniqby003

Primitive

import { uniqBy } from 'ramda';

let data = [1, 2, 3, -1];

uniqBy(x => Math.abs(x))(data); // ?

1-1 視為相同,我們希望結果只顯示 [1, 2, 3]

此時就不能再使用 uniq(),因為條件太特殊,只能使用 uniqBy()

第 5 行

uniqBy(x => Math.abs(x))(data); // ?

自行提供 x => Math.abs(x),如此 1-1 都視為相同。

uniqby004

Object

import { uniqBy } from 'ramda';

let data = [
  { title: 'FP in JavaScript', price: 100 },
  { title: 'RxJS in Action', price: 200 },
  { title: 'Speaking JavaScript', price: 300 },
  { title: 'FP in JavaScript', price: 400 }
];

console.dir(uniqBy(x => x.title)(data));

若 element 為 object,只要 title 相同就視為相同,也就是第一筆與第四筆,雖然 price 不同,但仍視為相同,我們希望結果只顯示不重複的前三筆。

此時就不能再使用 uniq(),因為條件太特殊,只能使用 uniqBy()

10 行

console.dir(uniqBy(x => x.title)(data));

自行提供 x => x.title,如此 object 只要 title 相同就視為相同。

uniq002

Point-free

import { uniqBy, prop } from 'ramda';

let data = [
  { title: 'FP in JavaScript', price: 100 },
  { title: 'RxJS in Action', price: 200 },
  { title: 'Speaking JavaScript', price: 300 },
  { title: 'FP in JavaScript', price: 400 }
];

console.dir(uniqBy(prop('title'))(data));

x => x.title 也可由 prop() 產生使其 point-free,可讀性更高。

uniq004

Conclusion

  • uniq() 也可使用 uniqBy(identity) 組合而成
  • uniq() 可視為簡易版;而 uniqBy() 為進階版 uniq()
  • 若只根據 object 特定 property 判斷 unique 條件,則要使用 uniqBy()

Reference

Ramda, uniq()
Ramda, uniqBy()
Ramda, identity()