如何从JavaScript中的对象数组中获取不同的值?

假设我有以下几点:

var array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]

能够获得所有不同年龄的数组的最佳方法是什么,以便我得到一个结果数组:

[17, 35]

有没有什么方法可以替代构建数据或更好的方法,这样我就不必遍历每个数组检查“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)
1102426 次浏览

如果这是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);
}

您可以使用像这样的字典方法。基本上,您将希望不同的值分配为“字典”中的键(这里我们使用数组作为对象以避免字典模式)。如果键不存在,则将该值添加为不同的。

以下是一个工作演示:

var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}];
var unique = [];
var distinct = [];
for( let i = 0; i < array.length; i++ ){
if( !unique[array[i].age]){
distinct.push(array[i].age);
unique[array[i].age] = 1;
}
}
var d = document.getElementById("d");
d.innerHTML = "" + distinct;
<div id="d"></div>

This will be O(n) where n is the number of objects in array and m is the number of unique values. There is no faster way than O(n) because you must inspect each value at least once.

The previous version of this used an object, and for in. These were minor in nature, and have since been minorly updated above. However, the reason for a seeming advance in performance between the two versions in the original jsperf was due to the data sample size being so small. Thus, the main comparison in the previous version was looking at the difference between the internal map and filter use versus the dictionary mode lookups.

I have updated the code above, as noted, however, I have also updated the jsperf to look through 1000 objects instead of 3. 3 overlooked many of the performance pitfalls involved (obsolete jsperf).

Performance

https://jsperf.com/filter-vs-dictionary-more-data When I ran this dictionary was 96% faster.

filter vs dictionary

我只是映射和删除dups:

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]

编辑: Aight!就性能而言,这不是最有效的方法,但在我看来,这是最简单易读的方法。如果你真的关心微优化,或者你有大量的数据,那么常规的for循环将更“高效”。

我已经开始在所有新项目中默认使用下划线,这样我就不必考虑这些小的数据修改问题。

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());

制作[17, 35]

@travis-j的答案的forEach版本(对现代浏览器和Node JS世界很有帮助):

var unique = {};
var distinct = [];
array.forEach(function (x) {
if (!unique[x.age]) {
distinct.push(x.age);
unique[x.age] = true;
}
});

Chromev29.0.1547:http://jsperf.com/filter-versus-dictionary/3快34%

还有一个采用mapper函数的通用解决方案(比直接map慢一点,但这是意料之中的):

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]

刚找到这个我觉得很有用

_.map(_.indexBy(records, '_id'), function(obj){return obj})

再次使用强调,因此如果您有这样的对象

var records = [{_id:1,name:'one', _id:2,name:'two', _id:1,name:'one'}]

它只会给你独特的对象。

这里发生的是indexBy返回这样的地图

{ 1:{_id:1,name:'one'}, 2:{_id:2,name:'two'} }

仅仅因为它是一张地图,所有的钥匙都是独一无二的。

然后我将这个列表映射回数组。

以防您只需要不同的值

_.map(_.indexBy(records, '_id'), function(obj,key){return key})

请记住,key是作为字符串返回的,因此,如果您需要整数,则应该这样做

_.map(_.indexBy(records, '_id'), function(obj,key){return parseInt(key)})

使用豆沙

var array = [
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
];
_.chain(array).pluck('age').unique().value();
> [17, 35]

这里有另一种方法来解决这个问题:

var result = {};
for(var i in array) {
result[array[i].age] = null;
}


result = Object.keys(result);

result = Object.values(result);

我不知道这个解决方案与其他解决方案相比有多快,但我喜欢更干净的外观。


编辑:好吧,上面的似乎是这里最慢的解决方案。

我在这里创建了一个性能测试用例: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);
}

使用Safari和Firefox的性能差异是惊人的,似乎Chrome在优化方面做得最好。

我不太确定为什么上面的片段与其他片段相比如此之快,也许比我聪明的人有答案。

我对这个函数的两分钱:

var result = [];
for (var len = array.length, i = 0; i < len; ++i) {
var age = array[i].age;
if (result.indexOf(age) > -1) continue;
result.push(age);
}

您可以在此处看到结果(方法8) http://jsperf.com/distinct-values-from-array/3

如果你有Array.prototype.includes或愿意聚填充,这是有效的:

var ages = []; array.forEach(function(x) { if (!ages.includes(x.age)) ages.push(x.age); });

使用ES6特性,您可以执行以下操作:

const uniqueAges = [...new Set( array.map(obj => obj.age)) ];

使用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]
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;
}

如果您使用的是ES6/ES2015或更高版本,您可以这样做:

const data = [
{ group: 'A', name: 'SD' },
{ group: 'B', name: 'FI' },
{ group: 'A', name: 'MM' },
{ group: 'B', name: 'CO'}
];
const unique = [...new Set(data.map(item => item.group))]; // [ 'A', 'B']

这里是如何做到这一点的一个例子。

如果像我一样,您更喜欢更“功能性”而不会影响速度,则此示例使用包装在Reduce闭包中的快速字典查找。

var array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]
var uniqueAges = array.reduce((p,c,i,a) => {
if(!p[0][c.age]) {
p[1].push(p[0][c.age] = c.age);
}
if(i<a.length-1) {
return p
} else {
return p[1]
}
}, [{},[]])

根据这个测试,我的解决方案比建议的答案快两倍

underscore.js _.uniq(_.pluck(array,"age"))

使用Lodash

var array = [
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
];


_.chain(array).map('age').unique().value();

返回[17,35]

这是一个通用的解决方案,它使用Reduce,允许映射并维护插入顺序。

项目:一个数组

映射器:将项映射到条件的单参函数,或为空以映射项本身。

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;
}, []);
}

用法

const distinctLastNames = distinct(items, (item)=>item.lastName);
const distinctItems = distinct(items);

您可以将其添加到数组原型中,如果这是您的风格,则省略项目参数…

const distinctLastNames = items.distinct( (item)=>item.lastName) ) ;
const distinctItems = items.distinct() ;

您还可以使用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());
}

使用新的Ecma功能很棒,但并非所有用户都有这些功能。

以下代码将一个名为不同的新函数附加到全局数组对象。 如果您尝试获取对象数组的不同值,您可以传递值的名称以获取该类型的不同值。

Array.prototype.distinct = function(item){   var results = [];
for (var i = 0, l = this.length; i < l; i++)
if (!item){
if (results.indexOf(this[i]) === -1)
results.push(this[i]);
} else {
if (results.indexOf(this[i][item]) === -1)
results.push(this[i][item]);
}
return results;};

查看CodePen中的我的帖子以获取演示。

我想你正在寻找group by函数(使用Lodash)

_personsList = [{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}];
_uniqAgeList = _.groupBy(_personsList,"age");
_uniqAges = Object.keys(_uniqAgeList);

产生结果:

17,35

jsFiddle演示:http://jsfiddle.net/4J2SX/201/

使用d3.jsv3

  ages = d3.set(
array.map(function (d) { return d.age; })
).values();

这就是你如何在2017年8月25日通过ES6使用新的Set来解决这个问题

TypeScript

 Array.from(new Set(yourArray.map((item: any) => item.id)))

JS

 Array.from(new Set(yourArray.map((item) => item.id)))
unique(obj, prop) {
let result = [];
let seen = new Set();


Object.keys(obj)
.forEach((key) => {
let value = obj[key];


let test = !prop
? value
: value[prop];


!seen.has(test)
&& seen.add(test)
&& result.push(value);
});


return result;
}

此函数可以唯一数组和对象

function oaunic(x,n=0){
if(n==0) n = "elem";
else n = "elem."+n;
var uval = [];
var unic = x.filter(function(elem, index, self){
if(uval.indexOf(eval(n)) < 0){
uval.push(eval(n));
return index == self.indexOf(elem);
}
})
return unic;
}

像这样使用它

tags_obj = [{name:"milad"},{name:"maziar"},{name:"maziar"}]
tags_arr = ["milad","maziar","maziar"]
console.log(oaunic(tags_obj,"name")) //for object
console.log(oaunic(tags_arr)) //for array

已经有很多有效的答案,但我想添加一个只使用reduce()方法的答案,因为它干净简单。

function uniqueBy(arr, prop){
return arr.reduce((a, d) => {
if (!a.includes(d[prop])) { a.push(d[prop]); }
return a;
}, []);
}

像这样使用它:

var array = [
{"name": "Joe", "age": 17},
{"name": "Bob", "age": 17},
{"name": "Carl", "age": 35}
];


var ages = uniqueBy(array, "age");
console.log(ages); // [17, 35]
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'));

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]

比我的测试中的ES6解决方案快6%。

var ages = array.map(function(o){return o.age}).filter(function(v,i,a) {
return a.indexOf(v)===i
});

我下面的代码将显示唯一的年龄数组以及没有重复年龄的新数组

var data = [
{"name": "Joe", "age": 17},
{"name": "Bob", "age": 17},
{"name": "Carl", "age": 35}
];


var unique = [];
var tempArr = [];
data.forEach((value, index) => {
if (unique.indexOf(value.age) === -1) {
unique.push(value.age);
} else {
tempArr.push(index);
}
});
tempArr.reverse();
tempArr.forEach(ele => {
data.splice(ele, 1);
});
console.log('Unique Ages', unique);
console.log('Unique Array', data);```

我知道这是一个古老且相对较好的问题,我给出的答案会让完整的对象回来(我在这篇文章的很多评论中看到了建议)。它可能“俗气”,但就易读性而言,似乎比许多其他解决方案更干净(尽管效率较低)。

这将返回数组内完整对象的唯一数组。

let productIds = data.map(d => {
return JSON.stringify({
id    : d.sku.product.productId,
name  : d.sku.product.name,
price : `${d.sku.product.price.currency} ${(d.sku.product.price.gross / d.sku.product.price.divisor).toFixed(2)}`
})
})
productIds = [ ...new Set(productIds)].map(d => JSON.parse(d))```

const array = [
{"id":"93","name":"CVAM_NGP_KW"},
{"id":"94","name":"CVAM_NGP_PB"},
{"id":"93","name":"CVAM_NGP_KW"},
{"id":"94","name":"CVAM_NGP_PB"}
]


function uniq(array, field) {
return array.reduce((accumulator, current) => {
if(!accumulator.includes(current[field])) {
accumulator.push(current[field])
}
return accumulator;
}, []
)
}


const ids = uniq(array, 'id');
console.log(ids)


/* output
["93", "94"]
*/

我用TypeScript编写了自己的代码,用于通用情况,例如静态编程语言Array.distinctBy {}

function distinctBy<T, U extends string | number>(array: T[], mapFn: (el: T) => U) {
const uniqueKeys = new Set(array.map(mapFn));
return array.filter((el) => uniqueKeys.has(mapFn(el)));
}

当然,其中U是可散列的。对于对象,您可能需要https://www.npmjs.com/package/es6-json-stable-stringify

如果您想从已知唯一对象属性的数组中过滤掉重复值,您可以使用以下片段:

let arr = [
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 },
{ "name": "Carl", "age": 35 }
];


let uniqueValues = [...arr.reduce((map, val) => {
if (!map.has(val.name)) {
map.set(val.name, val);
}
return map;
}, new Map()).values()]

如果你需要唯一的整个对象

const _ = require('lodash');


var objects = [
{ 'x': 1, 'y': 2 },
{ 'y': 1, 'x': 2 },
{ 'x': 2, 'y': 1 },
{ 'x': 1, 'y': 2 }
];


_.uniqWith(objects, _.isEqual);

[对象{x: 1, y: 2},对象{x: 2, y: 1}]

对于那些想要返回具有键唯一的所有属性的对象

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.

[...new Set([
{ "name": "Joe", "age": 17 },
{ "name": "Bob", "age": 17 },
{ "name": "Carl", "age": 35 }
].map(({ age }) => age))]

这里有很多很好的答案,但没有一个解决了以下问题:

有没有什么方法可以让我组织数据

我会创建一个对象,其键是年龄,每个都指向一个名称数组。

var array = [{ "name": "Joe", "age": 17 }, { "name": "Bob", "age": 17 }, { "name": "Carl", "age": 35 }];


var map = array.reduce(function(result, item) {
result[item.age] = result[item.age] || [];
result[item.age].push(item.name);
return result;
}, {});


console.log(Object.keys(map));
console.log(map);

这样,您就可以将数据结构转换为非常容易检索不同年龄的数据结构。

这是一个更紧凑的版本,它还存储整个对象而不仅仅是名称(如果您处理的对象具有超过2个属性,因此它们不能存储为键和值)。

var array = [{ "name": "Joe", "age": 17 }, { "name": "Bob", "age": 17 }, { "name": "Carl", "age": 35 }];


var map = array.reduce((r, i) => ((r[i.age] = r[i.age] || []).push(i), r), {});


console.log(Object.keys(map));
console.log(map);

我知道我的代码长度和时间复杂度很小,但这是可以理解的,所以我尝试了这种方式。

我试图在这里开发基于原型的函数,代码也会发生变化。

在这里,区分是我自己的原型函数。

<script>
var array = [{
"name": "Joe",
"age": 17
},
{
"name": "Bob",
"age": 17
},
{
"name": "Carl",
"age": 35
}
]


Array.prototype.Distinct = () => {
var output = [];
for (let i = 0; i < array.length; i++) {
let flag = true;
for (let j = 0; j < output.length; j++) {
if (array[i].age == output[j]) {
flag = false;
break;
}
}
if (flag)
output.push(array[i].age);
}
return output;
}
//Distinct is my own function
console.log(array.Distinct());
</script>

你可以用Lodash写一个代码这样代码就不会那么冗长了

方法1:嵌套方法

    let array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]
let result = _.uniq(_.map(array,item=>item.age))

方法2:方法链接或级联方法

    let array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]
let result = _.chain(array).map(item=>item.age).uniq().value()

您可以从https://lodash.com/docs/4.17.15#uniq中阅读有关洛达什的uniq()方法的信息

从一组键中获取不同值集合的方法。

您可以从这里获取给定代码并仅为所需键添加映射以获取唯一对象值的数组。

const
listOfTags = [{ id: 1, label: "Hello", color: "red", sorting: 0 }, { id: 2, label: "World", color: "green", sorting: 1 }, { id: 3, label: "Hello", color: "blue", sorting: 4 }, { id: 4, label: "Sunshine", color: "yellow", sorting: 5 }, { id: 5, label: "Hello", color: "red", sorting: 6 }],
keys = ['label', 'color'],
filtered = listOfTags.filter(
(s => o =>
(k => !s.has(k) && s.add(k))
(keys.map(k => o[k]).join('|'))
)(new Set)
)
result = filtered.map(o => Object.fromEntries(keys.map(k => [k, o[k]])));


console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

回答这个老问题是毫无意义的,但有一个简单的答案说明了Javascript的本质。Javascript中的对象本质上是哈希表。我们可以使用它来获取唯一键的哈希:

var o = {}; array.map(function(v){ o[v.age] = 1; });

然后我们可以将哈希减少为一个唯一值的数组:

var a2 = []; for (k in o){ a2.push(k); }

这就是您所需要的。数组a2仅包含唯一的年龄。

const array = [
{ "name": "Joe", "age": 17 },
{ "name":"Bob", "age":17 },
{ "name":"Carl", "age": 35 }
]


const allAges = array.map(a => a.age);


const uniqueSet = new Set(allAges)
const uniqueArray = [...uniqueSet]


console.log(uniqueArray)

使用集合和过滤器。这保留了顺序:

let unique = (items) => {
const s = new Set();
return items.filter((item) => {
if (s.has(item)) {
return false;
}
s.add(item);
return true;
});
}
  

console.log(
unique(
[
'one', 'two', 'two', 'three', 'three', 'three'
]
)
);


/*
output:
[
"one",
"two",
"three"
]
*/

linq.js-LINQ for JavaScript包(npm install linq),对于. Net开发人员来说应该很熟悉。

样品中显示的其他方法中,有不同的重载。

通过属性值从对象数组中区分对象的示例 是

Enumerable.from(array).distinct(“$.id”).toArray();

来自https://medium.com/@xmedeko/i-推荐-你-到-尝试-https-GitHub-com-mihaifm-linq-20a4e3c090e9

如果您想返回一个唯一的对象列表。 这里有另一个选择:

const unique = (arr, encoder=JSON.stringify, decoder=JSON.parse) =>
[...new Set(arr.map(item => encoder(item)))].map(item => decoder(item));

这将使这个:

unique([{"name": "john"}, {"name": "sarah"}, {"name": "john"}])

[{"name": "john"}, {"name": "sarah"}]

这里的技巧是我们首先使用JSON.stringify将项目编码为字符串,然后我们将其转换为Set(这使得字符串列表唯一),然后我们使用JSON.parse将其转换回原始对象。

使用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);

我随机抽取样本并对以下100,000个项目进行了测试:

let array=[]
for (var i=1;i<100000;i++){


let j= Math.floor(Math.random() * i) + 1
array.push({"name":"Joe"+j, "age":j})
}

以下是每个人的性能结果:

  Vlad Bezden Time:         === > 15ms
Travis J Time: 25ms       === > 25ms
Niet the Dark Absol Time: === > 30ms
Arun Saini Time:          === > 31ms
Mrchief Time:             === > 54ms
Ivan Nosov Time:          === > 14374ms

另外,我想提一下,由于项目是随机生成的,第二名是在Travis和Niet之间迭代。

如果您无法使用ES5,或者由于某种原因无法使用new Setnew Map,并且您需要一个包含具有唯一键的值的数组(而不仅仅是一个唯一键的数组),您可以使用以下内容:

function distinctBy(key, array) {
var keys = array.map(function (value) { return value[key]; });
return array.filter(function (value, index) { return keys.indexOf(value[key]) === index; });
}

或者TypeScript中的类型安全等价物:

public distinctBy<T>(key: keyof T, array: T[]) {
const keys = array.map(value => value[key]);
return array.filter((value, index) => keys.indexOf(value[key]) === index);
}

用法:

var distinctPeople = distinctBy('age', people);

所有其他答案要么:

  • 返回唯一键而不是对象的数组(例如返回年龄列表而不是具有唯一年龄的人);
  • 使用ES6,new Setnew Map等可能不可用;
  • 没有可配置的密钥(例如将.age硬编码到不同的函数中);
  • 假设键可用于索引数组,这并不总是true,TypeScript不允许它。

这个答案没有上述四个问题中的任何一个。

如果您的数组是对象数组,您可以使用此代码。

getUniqueArray = (array: MyData[]) => {
return array.filter((elem, index) => array.findIndex(obj => obj.value == elem.value) === index);
}

其中MyData如下所示:

export interface MyData{
value: string,
name: string
}

说明:您不能使用Set,因为当比较对象时,它们是通过引用而不是值进行比较的。因此,您需要唯一的键来比较对象,在我的示例中,唯一的键是值字段。 有关更多详细信息,您可以访问此链接:过滤JavaScript中唯一值的数组

我有个小办法

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);

假设我们有像这样的数据arr=[{id:1,age:17},{id:2,age:19} ...],那么我们可以找到像这样的独特对象-

function getUniqueObjects(ObjectArray) {
let uniqueIds = new Set();
const list = [...new Set(ObjectArray.filter(obj => {
if (!uniqueIds.has(obj.id)) {
uniqueIds.add(obj.id);
return obj;
}
}))];


return list;
}

点击这里代码链接

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);

原始类型

var unique = [...new Set(array.map(item => item.pritiveAttribute))];

对于复杂类型,例如对象

var unique = [...new DeepSet(array.map(item => item.Object))];


export class DeepSet extends Set {


add (o: any) {
for (let i of this)
if (this.deepCompare(o, i))
return this;
super.add.call(this, o);
return this;
};


private deepCompare(o: any, i: any) {
return JSON.stringify(o) === JSON.stringify(i)
}
}


如果您需要整个对象,这是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}]

const array = [{
"name": "Joe",
"age": 17
},
{
"name": "Bob",
"age": 17
},
{
"name": "Carl",
"age": 35
}
]


const uniqueArrayByProperty = (array, callback) => {
return array.reduce((prev, item) => {
const v = callback(item);
if (!prev.includes(v)) prev.push(v)
return prev
}, [])
}


console.log(uniqueArrayByProperty(array, it => it.age));

    var array =
[
{"name":"Joe", "age":17},
{"name":"Bob", "age":17},
{"name":"Carl", "age": 35}
]


console.log(Object.keys(array.reduce((r,{age}) => (r[age]='', r) , {})))

输出:

Array ["17", "35"]

let mobilePhones = [{id: 1, brand: "B1"}, {id: 2, brand: "B2"}, {id: 3, brand: "B1"}, {id: 4, brand: "B1"}, {id: 5, brand: "B2"}, {id: 6, brand: "B3"}]
let allBrandsArr = mobilePhones .map(row=>{
return  row.brand;
});
let uniqueBrands =   allBrandsArr.filter((item, index, arry) => (arry.indexOf(item) === index));
console.log('uniqueBrands   ', uniqueBrands );

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);

高效干净的方法,使用it-ops库:

import {pipe, distinct, map} from 'iter-ops';


const array =
[
{name: 'Joe', age: 17},
{name: 'Bob', age: 17},
{name: 'Carl', age: 35}
];


const i = pipe(
array,
distinct(a => a.age),
map(m => m.age)
);


const uniqueAges = [...i]; //=> [17, 35]

现在我们可以在相同键和相同值的基础上唯一对象

 const arr = [{"name":"Joe", "age":17},{"name":"Bob", "age":17}, {"name":"Carl", "age": 35},{"name":"Joe", "age":17}]
let unique = []
for (let char of arr) {
let check = unique.find(e=> JSON.stringify(e) == JSON.stringify(char))
if(!check) {
unique.push(char)
}
}
console.log(unique)

///输出:::[{name:"Joe", age: 17},{name:"Bob", age: 17},{name:"Carl", age: 35}]

如果你想遍历唯一的项目,使用这个:
(更灵活的https://stackoverflow.com/a/58429784/12496886版本)

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);

如果您只需要唯一值,请使用:
https://stackoverflow.com/a/35092559/12496886的副本,只是为了完整性)

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);

TypeScript类型安全功能方法中的@陈志立字典答案

const uniqueBy = <T, K extends keyof any>(
list: T[] = [],
getKey: (item: T) => K,
) => {
return list.reduce((previous, currentItem) => {
const keyValue = getKey(currentItem)
const { uniqueMap, result } = previous
const alreadyHas = uniqueMap[keyValue]
if (alreadyHas) return previous
return {
result: [...result, currentItem],
uniqueMap: { ...uniqueMap, [keyValue]: true }
}
}, { uniqueMap: {} as Record<K, any>, result: [] as T[] }).result
}


const array = [{ "name": "Joe", "age": 17 }, { "name": "Bob", "age": 17 }, { "name": "Carl", "age": 35 }];


console.log(uniqueBy(array, el => el.age))


// [
//     {
//         "name": "Joe",
//         "age": 17
//     },
//     {
//         "name": "Carl",
//         "age": 35
//     }
// ]