I can\'t find a similar question and I\'m a bit stuck. I have the following JSON array:
[
{
\"Name\": \"element1\",
\"Attributes\": [\"1\
With ES6/ES2015 you can use Set and the spread operator:
const input = [
{
"Name": "element1",
"Attributes": ["1", "2"]
},
{
"Name": "element2",
"Attributes": ["1","3" ]
},
{
"Name": "element3",
"Attributes": []
}
];
const output = [...new Set([].concat(...input.map(item => item.Attributes)))];
console.log(output);
Explanation (from the inside out):
input.map(item => item.Attributes)
produces an array of the Attributes arrays[].concat(...)
flattens the arrays, i.e. produces an array of all the Attributes values (including duplicates)new Set()
produces a Set from the array, i.e. stores only the unique Attribute values[...]
produces an array from the Set's values, i.e. produces an array of all unique Attribute valuesvar uniqueArr = [];
var arr = [
{
"Name": "element1",
"Attributes": ["1", "2"]
},
{
"Name": "element2",
"Attributes": ["1","3" ]
},
{
"Name": "element3",
"Attributes": []
}
];
arr.forEach(function(obj) {
var attr = obj.Attributes;
attr.forEach(function(val){
if (uniqueArray.indexOf(val) < 0) {
uniqueArray.push(val)
}
});
})
If lodash is an option, you can easily get what you want:
> _.chain(foo).map('Attributes').flatten().uniq().value()
["1", "2", "3"]
You can use Array#reduce and Array#filter methods
var data = [{
"Name": "element1",
"Attributes": ["1", "2"]
},
{
"Name": "element2",
"Attributes": ["1", "3"]
}, {
"Name": "element3",
"Attributes": []
}
]
console.log(
// iterate over array elements
data.reduce(function(arr, ele) {
// push the unique values to array
[].push.apply(arr,
// filter out unique value
ele.Attributes.filter(function(v) {
// check element present in array
return arr.indexOf(v) == -1;
})
);
// return the unique array
return arr;
// set initial argument as an empty array
}, [])
);
With ES6 arrow function
var data = [{
"Name": "element1",
"Attributes": ["1", "2"]
},
{
"Name": "element2",
"Attributes": ["1", "3"]
}, {
"Name": "element3",
"Attributes": []
}
]
console.log(
data.reduce((arr, ele) => ([].push.apply(arr, ele.Attributes.filter((v) => arr.indexOf(v) == -1)), arr), [])
);
Building on top of @dfsq answer, you could replace the two map
and reduce
with a single flatMap
var result = [
{
"Name": "element1",
"Attributes": ["1", "2"]
},
{
"Name": "element2",
"Attributes": ["1","3" ]
},
{
"Name": "element3",
"Attributes": []
}
]
// map & flatten to [ "1", "2", "1", "3" ]
.flatMap(item => item.Attributes)
// filter unique [ "1", "2", "3" ]
.filter((item, i, arr) => arr.indexOf(item) === i)
console.log(result)
You have answers to choose from. Just for fun: this one uses es6
"use strict";
let uniqueAttr = [];
const obj = [
{
"Name": "element1",
"Attributes": ["1", "2"]
},
{
"Name": "element2",
"Attributes": ["1","3" ]
},
{
"Name": "element3",
"Attributes": []
}
];
obj.forEach( element =>
element.Attributes.forEach(
attr => uniqueAttr.indexOf(attr) < 0 && uniqueAttr.push(attr)
)
);
document.querySelector("#result").textContent = uniqueAttr;
<pre id="result"></pre>