使用[. .new Set()]只获取基于内部Array<object.id>
Use [...new Set()] to get only uniques based off inner Array<object.id>?
是否可以使用[...new Set()]
返回基于内部id
值的唯一对象数组?如果这是不可能的,有没有其他聪明的ES6方法来实现这个输出?
参考:数组中的唯一值
var arr = [
{email: 'matthew@gmail.com', id: 10}
]
var arr2 = [
{email: 'matthew@gmail.com', id: 10},
{email: 'matthew@gmail.com', id: 13}
]
mergedArray = arr.concat(arr2);
console.log(
[...new Set(mergedArray)]
);
// output would be:
// [
// {email:'matthew@gmail.com', id: 10},
// {email:'matthew@gmail.com', id: 13}
// ]
要获得基于ID的唯一对象,您可以创建一个Map而不是Set,将它传递一个2元素数组作为迭代器,它将具有唯一键,然后获取它的值
var arr = [
{email: 'matthew@gmail.com', id: 10}
]
var arr2 = [
{email: 'matthew@gmail.com', id: 10},
{email: 'matthew@gmail.com', id: 13}
]
var mergedArray = arr.concat(arr2);
var map = new Map(mergedArray.map(o => [o.id,o]));
var unique = [...map.values()];
console.log(unique);
注意:这是目前为止最快的解决方案,请参阅jsperf.com上的测试用例。
我认为最好的解决方案是创建一个映射对象与id
s作为键,数组元素作为值。由于在一个对象中不可能有两个具有相同键的不同元素,因此重复的元素将被自动删除。然后,您可以使用Object.values()
函数将映射对象转换回数组(注意,这是ES 2017的一部分,而不是ES 6)。
const arr = [
{ email: 'matthew@gmail.com', id: 10 },
];
const arr2 = [
{ email: 'matthew@gmail.com', id: 10 },
{ email: 'matthew@gmail.com', id: 13 },
];
const mergedArray = [...arr, ...arr2];
const map = {};
for (const element of mergedArray) {
map[element.id] = element;
}
const newArray = Object.values(map);
console.log(newArray);
另外,您可以使用扩展操作符:[...arr, ...arr2]
来代替arr.concat(arr2)
。
由于这被标记为函数式编程,因此我将提供一种使用泛型过程的更函数化的方法
我的unionBy
实现使用了一个底层Set,但是这个实现细节没有泄露给使用它的函数。相反,通过将过滤谓词控制作为高阶函数传递给"联合"过程,可以反转过滤谓词控制。这一点很重要,因为函数的用户不应该关心是否使用了Set。也许集合是最理想的,但在其他情况下可能不是。无论哪种方式,最好是由unionBy
过程的用户声明分组值是什么,而不是其他任何东西。
为了理解我的意思,让我们首先看一下unionById
——它接受两个Object类型的数组,并返回一个Object类型的数组。
// unionById :: [Object] -> [Object] -> [Object]
const unionById = unionBy (p=> x=> p (x.id));
这里,unionBy
的第一个参数是一个用户定义的过程,但是过程的第一个参数本身将期望另一个过程,在本例中是p
。您的过程的第二个参数(在本例中是x
)将是要检查的单个元素。您只需将"分组"值返回给p
。因为我们要按x
的id
字段分组,所以我们只需调用p(x.id)
这是一个可运行的代码片段
// id :: a -> a
const id = x=> x
// unionBy :: ((a -> b) -> a -> b) -> [c] -> [c] -> [c]
const unionBy = p=> xs=> ys=> {
let s = new Set (xs.map (p (id)));
let zs = ys.filter (p (z => s.has (z) ? false : s.add (z)));
return xs.concat (zs);
};
// unionById :: [Object] -> [Object] -> [Object]
const unionById = unionBy (p=> x=> p (x.id));
// your data
var arr = [
{email: 'matthew@gmail.com', id: 10}
]
var arr2 = [
{email: 'matthew@gmail.com', id: 10},
{email: 'matthew@gmail.com', id: 13}
]
// check it out
console.log(unionById(arr)(arr2))
如果你看看非常通用的union
// apply :: (a -> b) -> a -> b
const apply = f=> x=> f(x)
// union :: [a] -> [a] -> [a]
const union = unionBy (apply);
union ([1,2,3]) ([2,3,4]);
// => [ 1, 2, 3, 4 ]
unionBy
是强大的,因为它没有假设输入将是什么。在我们将它用于对象数组之前-这里你将看到它在字符串数组上工作。
let xs = ['A', 'B', 'C'];
let ys = ['a', 'b', 'x', 'y'];
unionBy (p=> x=> p(x.toLowerCase())) (xs) (ys);
// => [ 'A', 'B', 'C', 'x', 'y']
你可能想要unionByAll
接受2个或更多的输入数组
// uncurry :: (a -> b -> c) -> (a,b) -> c
const uncurry = f=> (x,y)=> f (x) (y);
// unionByAll :: ((a -> b) -> a -> b) -> [[c]] -> [c]
const unionByAll = p=> (x,...xs)=> {
return xs.reduce (uncurry (unionBy (p)), x);
};
unionByAll (apply) ([1,2,3], [2,3,4], [3,4,5]);
// => [ 1, 2, 3, 4, 5 ]
Care: @adeneo指出
unionBy
对初始输入没有任何假设。根据设计,unionBy
不检查初始输入中的重复-它是而不是一个交换过程。
// "duplicates" in xs will not be removed
unionBy (f) (xs) (ys)
// "duplicates" in ys will not be removed
unionBy (f) (ys) (xs)
如果您在一个或多个输入中有潜在的重复,使用unionByAll
将帮助您
// "duplicates" in both xs and ys will now be removed
unionByAll (f) ([], xs, ys)
这将是我的方法,不使用Set
,但Map
:
const uniques = mergedArray
.reduce((map, item) => map.set(item.id, item), new Map())
.values();
这给了你一个可迭代对象,它可能满足你的需要,也可能不满足你的需要。
- E4X中是否有一种方法可以将基元数据类型的XMLList转换为类似于Array.join()的Array
- 相对于他在jQuery/Js中的一个内部数据对数组进行排序
- 检查数组中的项是否存在于对象内部
- Array.prototype.stice.call()的内部工作
- 困惑于我应该从哪里开始分页{$.getJSON,php image array}
- 是否存在相当于“;new Array(number)”;在javascript中
- 如何确定相对于内部每个字符的页面的位置(x,y)跨越javascript
- 使用内部脚本更改表单元格 css,而不依赖于 id、类或包含
- document.getElementById 对内部 html 的调用适用于 $_POST 和 $_GET 变量,但不
- 使用类似于 Array.prototype.map() 的方法将数组转换为键值对象
- Javascript Array Push 代码如何在内部工作
- Javascript Array.indexOf() 在应用于对象数组时表现出奇怪的行为
- Javascript onClick在array.map内部分配时未激发
- 将JavaScript函数应用于除第i个元素之外的所有Array元素
- Javascript array.prototype.every在函数内部不起作用
- 为什么String.prototype会记录它's对象类似于标准对象,而Array.prototype记录它
- 效果类似于html5画布中的内部辉光
- CSS或JS规则适用于所有Div更改Div内部Div的BG颜色,而不更改父Div
- 获取可拖动元素相对于元素内部的位置
- 固定应用于内部Div禁用溢出:隐藏