在这个片段中,我被困在
_.uniqBy(array, iteratee)
中。这个
iteratee
可以同时是函数或字符串var sourceArray = [ { id: 1, name: 'bob' },
{ id: 1, name: 'bill' },
{ id: 1, name: 'bill' } ,
{id: 2,name: 'silly'},
{id: 2,name: 'billy'}]
function uniqBy (inputArray, callback) {
return inputArray.filter(callback)
}
var inputFunc = function (item) {
return item.name
}
// var destArray = _.uniqBy(sourceArray,'name')
var destArray = uniqBy(sourceArray, inputFunc)
console.log('destArray', destArray)
解决办法是什么?
使用
uniqBy
的 ES6
Map
,复杂度为 O(n):
const uniqBy = (arr, predicate) => {
const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
return [...arr.reduce((map, item) => {
const key = (item === null || item === undefined) ?
item : cb(item);
map.has(key) || map.set(key, item);
return map;
}, new Map()).values()];
};
const sourceArray = [
{ id: 1, name: 'bob' },
{ id: 1, name: 'bill' },
null,
{ id: 1, name: 'bill' } ,
{ id: 2,name: 'silly'},
{ id: 2,name: 'billy'},
null,
undefined
];
console.log('id string: ', uniqBy(sourceArray, 'id'));
console.log('name func: ', uniqBy(sourceArray, (o) => o.name));
我重构了ori-drori的解决方案并删除了
undefined
null
[]
则返回
Array
const uniqBy = (arr, predicate) => {
if (!Array.isArray(arr)) { return []; }
const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
const pickedObjects = arr
.filter(item => item)
.reduce((map, item) => {
const key = cb(item);
if (!key) { return map; }
return map.has(key) ? map : map.set(key, item);
}, new Map())
.values();
return [...pickedObjects];
};
const a = [
12,
undefined,
{ id: 1, name: 'bob' },
null,
{ id: 1, name: 'bill' },
null,
undefined
];
const b = [
12,
{ id: 1, name: 'bob' },
{ id: 1, name: 'bill' },
];
uniqBy(a, 'name');
uniqBy(b, Math.floor);
uniqBy([2.1, 1.2, 2.3], Math.floor);
我正在通过 CreateReactApp 通过 Webpack 运行我的代码,它必须使用使用切片的 polyfill 进行传播。这就是我所做的,@oridori 答案的变体:
const uniqBy = (arr: any[], predicate: (item: any) => string) => {
const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
const result = [];
const map = new Map();
arr.forEach((item) => {
const key = (item === null || item === undefined) ? item : cb(item);
if (!map.has(key)) {
map.set(key, item);
result.push(item);
}
});
return result;
};
对于那些寻找一行答案的人:
const inputArr = [
{ id: 1, name: { first: 'bob' } },
{ id: 1, name: { first: 'bill' } },
{ id: 1, name: { first: 'bill' } },
{ id: 1 },
undefined,
{ id: 2, name: { first: 'silly' } },
{ id: 2, name: { first: 'billy' } }
]
var uniqBy = (arr, key) => {
return Object.values([...arr].reverse().reduce((m, i) => {m[key.split('.').reduce((a, p) => a?.[p], i)] = i; return m;}, {}))
}
console.log(uniqBy(inputArr, 'id'))
console.log(uniqBy(inputArr, 'name.first'))
您可以使用按名称排序的排序和基于邻域比较的过滤器,如下所示:
var sourceArray = [ { id: 1, name: 'bob' },
{ id: 1, name: 'bill' },
{ id: 1, name: 'bill' } ,
{id: 2,name: 'silly'},
{id: 2,name: 'billy'}]
var uniqBy = (inputArray, callback) => inputArray.sort((a,b) => callback(a) > callback(b))
.filter((x,i,arr) => i === arr.length -1 ? true : callback(x) !== callback(arr[i+1]));
var inputFunc = item => item.name;
var destArray = uniqBy(sourceArray, inputFunc)
console.log('destArray', destArray)