Search code examples
javascriptarraysloopsnested-loops

Create array of objects using distinct values from two arrays with javascript


My question is a little more involved. I have two arrays of data:

var arr = [
  {title: "foo", namesIndices: [0,1]},
  {title: "bar", namesIndices: [2]},
  {title: "baz", namesIndices: [3,4]}
];

var names = [
  {name: "John", website: "someUrl"},
  {name: "Mike", website: "someUrl"},
  {name: "Jane", website: "someUrl"},
  {name: "Ali", website: "someUrl"},
  {name: "Robert", website: "someUrl"}
];

Where namesIndices will reference an index in the names array that will correspond with that person with their title. In order to match the person's name and website with the correct title to make this array:

var person = [
  {name: "John", title: "foo", website: "someUrl"},
  {name: "Mike", title: "foo", website: "someUrl"},
  {name: "Jane", title: "bar", website: "someUrl"},
  {name: "Ali", title: "baz", website: "someUrl"},
  {name: "Robert", title: "baz", website: "someUrl"}
];

I have had to loop through the first array, then loop through arr.namesIndices:

var person = [];
for (var i = 0; i < arr.length; i++) {
    for (var j = 0; j < arr[i].namesIndices.length; j++) {
        var personObj = {};
        personObj.title= arr[i].title;
        personObj.name = names[arr[i].namesIndices[j]].name;
        personObj.website= names[arr[i].namesIndices[j]].website;
        person.push(personObj);
     }
 }

Is there a way to do this without nested loops?


Solution

  • You can use reduce() and map() to avoid explicit loops altogether if you wish.

    var arr = [
      {title: "foo", namesIndices: [0,1]},
      {title: "bar", namesIndices: [2]},
      {title: "baz", namesIndices: [3,4]}
    ];
    
    var names = [
      {name: "John", website: "someUrl"},
      {name: "Mike", website: "someUrl"},
      {name: "Jane", website: "someUrl"},
      {name: "Ali", website: "someUrl"},
      {name: "Robert", website: "someUrl"}
    ];
    
    var person = arr.reduce(function (accumulator, titleAndIndices, arrIndex) {
        var newEntries = titleAndIndices.namesIndices.map(function (index) {
            var rv = names[index];
            rv.title = arr[arrIndex].title;
            return rv;
        });
        return accumulator.concat(newEntries);
    }, []);
    
     console.log(person);