简体   繁体   中英

Return unique array values from an array inside an array of objects

I can't find a similar question and I'm a bit stuck. I have the following JSON array:

[
    {
        "Name": "element1",
        "Attributes": ["1", "2"]
    },

    {
        "Name": "element2",
        "Attributes": ["1","3" ]
    },
    {
        "Name": "element3",
        "Attributes": []
    }
]

I'm trying to create an array of all the unique elements in the "Attributes" property, but I'm having trouble looping through each object, and then looping through the array elements to return the unique values. I'm trying to do it with filter(), or map() preferably.

EDIT: I want an array of unique elements, so: [1,2,3].

You could do it with couple of Array methods. For example:

 var result = [ { "Name": "element1", "Attributes": ["1", "2"] }, { "Name": "element2", "Attributes": ["1","3" ] }, { "Name": "element3", "Attributes": [] } ] // map to [ ["1", "2"], ["1", "3"], [] ] .map(item => item.Attributes) // flatten to [ "1", "2", "1", "3" ] .reduce((prev, curr) => prev.concat(curr), []) // filter unique [ "1", "2", "3" ] .filter((item, i, arr) => arr.indexOf(item) === i) console.log(result)

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

If lodash is an option, you can easily get what you want:

> _.chain(foo).map('Attributes').flatten().uniq().value()
["1", "2", "3"]
var 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)
       }
   });
})

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>

Try This, It'll help to solve this problem.

 var data = [{ "Name": "element1", "Attributes": ["1", "2"] }, { "Name": "element2", "Attributes": ["1", "3"] }, { "Name": "element3", "Attributes": [] }]; var Attributes = []; $.each(data, function(i, e) { $.each(e.Attributes, function(i, e) { Attributes.push(parseInt(e)); }); }); Attributes = $.unique(Attributes); alert(Attributes);
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

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, ie produces an array of all the Attributes values (including duplicates)
  • new Set() produces a Set from the array, ie stores only the unique Attribute values
  • [...] produces an array from the Set's values, ie produces an array of all unique Attribute values

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM