Rol*_*ndo 325 javascript arrays unique
假设我有以下内容:
var array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]
Run Code Online (Sandbox Code Playgroud)
能够获得所有不同年龄的数组的最佳方法是什么,以便我得到一个结果数组:
[17, 35]
Run Code Online (Sandbox Code Playgroud)
有没有办法我可以选择构造数据或更好的方法,这样我就不必遍历每个数组检查"age"的值并检查另一个数组是否存在,如果没有则添加它?
如果有某种方式我可以在没有迭代的情况下拉出不同的年龄......
我希望改进的当前无效方式......如果它意味着不是"数组"是一个对象数组,而是一个带有一些唯一键(即"1,2,3")的对象的"地图"好的 我只是在寻找性能最高效的方式.
以下是我目前的做法,但对我来说,虽然迭代确实有效,但迭代看起来效率很高......
var distinct = []
for (var i = 0; i < array.length; i++)
if (array[i].age not in distinct)
distinct.push(array[i].age)
Run Code Online (Sandbox Code Playgroud)
Vla*_*den 475
如果您使用的是ES6/ES2015或更高版本,则可以这样做:
const unique = [...new Set(array.map(item => item.age))];
Run Code Online (Sandbox Code Playgroud)
Aru*_*ini 143
对于那些想要返回具有键唯一属性的对象的人
const array =
[
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
]
const key = 'age';
const arrayUniqueByKey = [...new Map(array.map(item =>
[item[key], item])).values()];
console.log(arrayUniqueByKey);
/*OUTPUT
[
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
]
*/
// Note: this will pick the last duplicated item in the list.Run Code Online (Sandbox Code Playgroud)
小智 139
使用ES6
let array = [
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
];
array.map(item => item.age)
.filter((value, index, self) => self.indexOf(value) === index)
> [17, 35]
Run Code Online (Sandbox Code Playgroud)
Nie*_*sol 117
如果这是PHP,我会用键构建一个数组,并array_keys在最后,但JS没有这样的奢侈.相反,试试这个:
var flags = [], output = [], l = array.length, i;
for( i=0; i<l; i++) {
if( flags[array[i].age]) continue;
flags[array[i].age] = true;
output.push(array[i].age);
}
Run Code Online (Sandbox Code Playgroud)
Tra*_*s J 116
您可以使用像这样的字典方法.基本上,您将要分离的值指定为字典中的键.如果密钥不存在,则将该值添加为distinct.
var unique = {};
var distinct = [];
for( var i in array ){
if( typeof(unique[array[i].age]) == "undefined"){
distinct.push(array[i].age);
}
unique[array[i].age] = 0;
}
Run Code Online (Sandbox Code Playgroud)
这是一个工作演示:http://jsfiddle.net/jbUKP/1
这将是O(n),其中n是数组中对象的数量,m是唯一值的数量.没有比O(n)更快的方法,因为你必须至少检查一次每个值.
性能
http://jsperf.com/filter-versus-dictionary当我运行这本词典的速度提高了30%.
Chr*_*hew 68
这就是你如何使用新的Set by ES6 for Typescript来解决这个问题,截至2017年8月25日
Array.from(new Set(yourArray.map((item: any) => item.id)))
Run Code Online (Sandbox Code Playgroud)
小智 67
使用ES6功能,您可以执行以下操作:
const uniqueAges = [...new Set( array.map(obj => obj.age)) ];
Run Code Online (Sandbox Code Playgroud)
elc*_*nrs 59
我只是映射并删除重复:
var ages = array.map(function(obj) { return obj.age; });
ages = ages.filter(function(v,i) { return ages.indexOf(v) == i; });
console.log(ages); //=> [17, 35]
Run Code Online (Sandbox Code Playgroud)
编辑: Aight!在性能方面不是最有效的方式,而是最简单最易读的IMO.如果您真的关心微优化或者您拥有大量数据,那么常规for循环将更加"高效".
Cip*_*ian 54
如果您需要整个对象,这与 ES6 版本略有不同:
let arr = [
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]
arr.filter((a, i) => arr.findIndex((s) => a.age === s.age) === i) // [{"name":"Joe", "age":17}, {"name":"Carl", "age": 35}]
Run Code Online (Sandbox Code Playgroud)
7gu*_*uyo 32
您可能对基于其中一个键的唯一对象集感兴趣:
const array = [
{"name": "Joe", "age": 17},
{"name": "Bob", "age": 17},
{"name": "Carl", "age": 35}
];
const distinctItems = [...new Map(array.map(item => [item["age"], item])).values()];
Run Code Online (Sandbox Code Playgroud)
结果:
[
{name: "Bob", age: 17},
{name: "Carl", age: 35}
]
Run Code Online (Sandbox Code Playgroud)
ole*_*eac 31
var unique = array
.map(p => p.age)
.filter((age, index, arr) => arr.indexOf(age) == index)
.sort(); // sorting is optional
// or in ES6
var unique = [...new Set(array.map(p => p.age))];
// or with lodash
var unique = _.uniq(_.map(array, 'age'));
Run Code Online (Sandbox Code Playgroud)
ES6示例
const data = [
{ name: "Joe", age: 17},
{ name: "Bob", age: 17},
{ name: "Carl", age: 35}
];
const arr = data.map(p => p.age); // [17, 17, 35]
const s = new Set(arr); // {17, 35} a set removes duplications, but it's still a set
const unique = [...s]; // [17, 35] Use the spread operator to transform a set into an Array
// or use Array.from to transform a set into an array
const unique2 = Array.from(s); // [17, 35]
Run Code Online (Sandbox Code Playgroud)
Rub*_*lix 21
const x = [
{"id":"93","name":"CVAM_NGP_KW"},
{"id":"94","name":"CVAM_NGP_PB"},
{"id":"93","name":"CVAM_NGP_KW"},
{"id":"94","name":"CVAM_NGP_PB"}
].reduce(
(accumulator, current) => {
if(!accumulator.some(x => x.id === current.id)) {
accumulator.push(current)
}
return accumulator;
}, []
)
console.log(x)
/* output
[
{ id: '93', name: 'CVAM_NGP_KW' },
{ id: '94', name: 'CVAM_NGP_PB' }
]
*/Run Code Online (Sandbox Code Playgroud)
Mrc*_*ief 20
在forEach@特拉维斯-J的答案的版本(在现代的浏览器有用和节点JS世界):
var unique = {};
var distinct = [];
array.forEach(function (x) {
if (!unique[x.age]) {
distinct.push(x.age);
unique[x.age] = true;
}
});
Run Code Online (Sandbox Code Playgroud)
Chrome v29.0.1547上的速度提高了34%:http://jsperf.com/filter-versus-dictionary/3
一个采用映射器函数的通用解决方案(比直接映射慢,但这是预期的):
function uniqueBy(arr, fn) {
var unique = {};
var distinct = [];
arr.forEach(function (x) {
var key = fn(x);
if (!unique[key]) {
distinct.push(key);
unique[key] = true;
}
});
return distinct;
}
// usage
uniqueBy(array, function(x){return x.age;}); // outputs [17, 35]
Run Code Online (Sandbox Code Playgroud)
Har*_*ens 17
已经有很多有效的答案,但我想添加一个只使用该reduce()方法的答案, 因为它简洁明了.
function uniqueBy(arr, prop){
return arr.reduce((a, d) => {
if (!a.includes(d[prop])) { a.push(d[prop]); }
return a;
}, []);
}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
var array = [
{"name": "Joe", "age": 17},
{"name": "Bob", "age": 17},
{"name": "Carl", "age": 35}
];
var ages = uniqueBy(array, "age");
console.log(ages); // [17, 35]
Run Code Online (Sandbox Code Playgroud)
Boa*_*ges 14
const array =
[
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
]
const key = 'age';
const arrayUniqueByKey = [...new Map(array.map(item =>
[item[key], item])).values()];
console.log(arrayUniqueByKey);Run Code Online (Sandbox Code Playgroud)
Eev*_*vee 13
我开始坚持下划线默认情况下,所有新项目,这样我从来没有去想这些小数据改写(munging)的问题.
var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}];
console.log(_.chain(array).map(function(item) { return item.age }).uniq().value());
Run Code Online (Sandbox Code Playgroud)
生产[17, 35].
BaM*_*BaM 13
这是解决此问题的另一种方法:
var result = {};
for(var i in array) {
result[array[i].age] = null;
}
result = Object.keys(result);
Run Code Online (Sandbox Code Playgroud)
我不知道这个解决方案与其他解决方案相比有多快,但我喜欢更干净的外观.;-)
编辑:好的,上面似乎是所有这里最慢的解决方案.
我在这里创建了一个性能测试用例:http://jsperf.com/distinct-values-from-array
我没有测试年龄(整数),而是选择比较名称(字符串).
方法1(TS的解决方案)非常快.有趣的是,方法7优于所有其他解决方案,在这里我只是摆脱.indexOf()并使用它的"手动"实现,避免循环函数调用:
var result = [];
loop1: for (var i = 0; i < array.length; i++) {
var name = array[i].name;
for (var i2 = 0; i2 < result.length; i2++) {
if (result[i2] == name) {
continue loop1;
}
}
result.push(name);
}
Run Code Online (Sandbox Code Playgroud)
使用Safari和Firefox的性能差异令人惊叹,Chrome似乎在优化方面做得最好.
我不确定为什么上面的片段与其他片段相比如此之快,也许比我更聪明的人有答案.;-)
Ali*_*igy 13
我有一个小解决方案
let data = [{id: 1}, {id: 2}, {id: 3}, {id: 2}, {id: 3}];
let result = data.filter((value, index, self) => self.findIndex((m) => m.id === value.id) === index);
Run Code Online (Sandbox Code Playgroud)
使用 Maps 的简单不同过滤器:
let array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
];
let data = new Map();
for (let obj of array) {
data.set(obj.age, obj);
}
let out = [...data.values()];
console.log(out);Run Code Online (Sandbox Code Playgroud)
小智 8
使用lodash
var array = [
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
];
_.chain(array).pluck('age').unique().value();
> [17, 35]
Run Code Online (Sandbox Code Playgroud)
function get_unique_values_from_array_object(array,property){
var unique = {};
var distinct = [];
for( var i in array ){
if( typeof(unique[array[i][property]]) == "undefined"){
distinct.push(array[i]);
}
unique[array[i][property]] = 0;
}
return distinct;
}
Run Code Online (Sandbox Code Playgroud)
使用Lodash
var array = [
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
];
_.chain(array).map('age').unique().value();
Run Code Online (Sandbox Code Playgroud)
退货[17,35]
如果您想返回一个唯一的对象列表。这是另一种选择:
const unique = (arr, encoder=JSON.stringify, decoder=JSON.parse) =>
[...new Set(arr.map(item => encoder(item)))].map(item => decoder(item));
Run Code Online (Sandbox Code Playgroud)
这将变成:
unique([{"name": "john"}, {"name": "sarah"}, {"name": "john"}])
Run Code Online (Sandbox Code Playgroud)
进入
[{"name": "john"}, {"name": "sarah"}]
Run Code Online (Sandbox Code Playgroud)
这里的技巧是,我们首先使用 将项目编码为字符串JSON.stringify,然后将其转换为 Set(这使得字符串列表唯一),然后使用 将其转换回原始对象JSON.parse。
var array = [
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
];
const ages = [...new Set(array.reduce((a, c) => [...a, c.age], []))];
console.log(ages);Run Code Online (Sandbox Code Playgroud)
如果您想迭代独特的项目,请使用此:(
更灵活的版本/sf/answers/4090084911/)
const array = [
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35},
];
const uniqBy = (arr, selector = (item) => item) => {
const map = new Map();
arr.forEach((item) => {
const prop = selector(item);
if (!map.has(prop)) map.set(prop, item);
});
return [...map.values()];
}
const uniqItems = uniqBy(array, (item) => item.age);
console.log('uniqItems: ', uniqItems);Run Code Online (Sandbox Code Playgroud)
如果您只需要唯一值,请使用此:(
重复/sf/answers/2456479161/,只是为了完整性)
const array = [
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35},
];
const uniq = (items) => [...new Set(items)];
const uniqAges = uniq(array.map((item) => item.age));
console.log('uniqAges: ', uniqAges);Run Code Online (Sandbox Code Playgroud)
这是一个通用的解决方案,它使用reduce,允许映射并保持插入顺序。
项目:数组
mapper:一个将项目映射到条件的一元函数,或者为空以映射项目本身。
function distinct(items, mapper) {
if (!mapper) mapper = (item)=>item;
return items.map(mapper).reduce((acc, item) => {
if (acc.indexOf(item) === -1) acc.push(item);
return acc;
}, []);
}
Run Code Online (Sandbox Code Playgroud)
用法
const distinctLastNames = distinct(items, (item)=>item.lastName);
const distinctItems = distinct(items);
Run Code Online (Sandbox Code Playgroud)
您可以将其添加到Array原型中,如果这是您的样式,则可以省略items参数。
const distinctLastNames = items.distinct( (item)=>item.lastName) ) ;
const distinctItems = items.distinct() ;
Run Code Online (Sandbox Code Playgroud)
您也可以使用Set而不是Array来加快匹配速度。
function distinct(items, mapper) {
if (!mapper) mapper = (item)=>item;
return items.map(mapper).reduce((acc, item) => {
acc.add(item);
return acc;
}, new Set());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
403710 次 |
| 最近记录: |