Map two arrays to merge different data in one IF item id is the same in javascript

Viewed 48

thanks to another post I could mange a step ahead in what I taught was an easy process to do.. but it seems I cannot manage a proper way to merge two arrays into one, by "grouping" per an "id" common field...

Below is my one array:

// editedItem.extra_tools ///

0:
{
    extra_tool_password: "tool data password"
    extra_tool_username: "tool data username"
    id_extra_tool: "8"
},
1:
{
    extra_tool_password: "tool data password"
    extra_tool_username: "tool data username"
    id_extra_tool: "1"
},
2:
{
    extra_tool_password: "tool data password"
    extra_tool_username: "tool data username"
    id_extra_tool: "7"
}

this should be merged, via id_extra_tool to:

// this.extras //
0:
{
    extra_params: 1
    extra_tool_name: "tool 1"
    extra_tool_password: ""
    extra_tool_username: ""
    id_extra_tool: 1
}
1:
{
    extra_params: 1
    extra_tool_name: "tool 2"
    extra_tool_password: ""
    extra_tool_username: ""
    id_extra_tool: 7
}
{
2:
    extra_params: 0
    extra_tool_name: "tool 3"
    extra_tool_password: ""
    extra_tool_username: ""
    id_extra_tool: 8

to get a

//mergedArray //

if (this.editedItem.extra_tools.length) {
        var mergedArray = []
        this.editedItem.extra_tools.map(x => {
          this.extras.map(y => {
            if (x.id_extra_tool === y.id_extra_tool) {
              mergedArray.push(Object.assign(x, y))
            }
          })
        })

so the final array should contain "full" data from each array, completing each item merging data by id_extra_tool

// merged //
0:
{
    extra_params: // TAKEN_BY: "Extras"
    extra_tool_name: // TAKEN_BY: "Extras"
    extra_tool_password:// TAKEN_BY: "extra_tools"
    extra_tool_username: // TAKEN_BY: "extra_tools"
    id_extra_tool: 1
}
1:
{
    extra_params: // TAKEN_BY: "Extras"
    extra_tool_name: // TAKEN_BY: "Extras"
    extra_tool_password:// TAKEN_BY: "extra_tools"
    extra_tool_username: // TAKEN_BY: "extra_tools"
    id_extra_tool: 7
}
{
2:
    extra_params: // TAKEN_BY: "Extras"
    extra_tool_name: // TAKEN_BY: "Extras"
    extra_tool_password:// TAKEN_BY: "extra_tools"
    extra_tool_username: // TAKEN_BY: "extra_tools"
    id_extra_tool: 8
3 Answers

The id_extra_tool in editedItem.extra_tools and this.extras are not same type (string vs number) so the comparison x.id_extra_tool === y.id_extra_tool will always return false, try change to use == instead.

Short example use map:

const mergedArray = this.extras.map(item => ({
  ...item,
  ...editedItem.extra_tools.find(i => i.id_extra_tool == item.id_extra_tool)
}));

You are trying to compare string with integer using === which is wrong (use == instead).

It is better to use .find to check if each x element has a corresponding object in extras with the same id_extra_tool:

const editedItem = {
  extra_tools: [
    {
      extra_tool_password: "tool data password",
      extra_tool_username: "tool data username",
      id_extra_tool: "8"
    },
    {
      extra_tool_password: "tool data password",
      extra_tool_username: "tool data username",
      id_extra_tool: "1"
    },
    {
      extra_tool_password: "tool data password",
      extra_tool_username: "tool data username",
      id_extra_tool: "7"
    }
  ]
};
const extras = [
  {
    extra_params: 1,
    extra_tool_name: "tool 1",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 1
  },
  {
    extra_params: 1,
    extra_tool_name: "tool 2",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 7
  },
  {
    extra_params: 0,
    extra_tool_name: "tool 3",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 8
  }
];

if (editedItem.extra_tools.length) {

  var mergedArray = [];
  
  editedItem.extra_tools.map(x => {
  
    const y = extras.find(e => e.id_extra_tool == x.id_extra_tool);
    
    if (y) {
      mergedArray.push(Object.assign(x, y))
    }
  });
  
  console.log(mergedArray);
}

Another way to do this would be using .reduce:

const editedItem = {
  extra_tools: [
    {
      extra_tool_password: "tool data password",
      extra_tool_username: "tool data username",
      id_extra_tool: "8"
    },
    {
      extra_tool_password: "tool data password",
      extra_tool_username: "tool data username",
      id_extra_tool: "1"
    },
    {
      extra_tool_password: "tool data password",
      extra_tool_username: "tool data username",
      id_extra_tool: "7"
    }
  ]
};
const extras = [
  {
    extra_params: 1,
    extra_tool_name: "tool 1",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 1
  },
  {
    extra_params: 1,
    extra_tool_name: "tool 2",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 7
  },
  {
    extra_params: 0,
    extra_tool_name: "tool 3",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 8
  }
];

if (editedItem.extra_tools.length) {

  const mergedArray = editedItem.extra_tools.reduce((acc,x) => {
  
    const y = extras.find(e => e.id_extra_tool == x.id_extra_tool);
    
    if (y) {
      acc.push(Object.assign(x, y))
    }
    
    return acc;
  }, []);
  
  console.log(mergedArray);
}

First I would build one array into key/value object using id_extra_tool as the object key, assuming that id_extra_tool is always unique. This helps to improve performance.

Then merge with the second array

// build key/value object
obj = {};
editedItem.extra_tools.map((value) => {
  obj[value.id_extra_tool] = value;
});

// iterate other array and merge
const result = this.extras.map((extra) => {
  return Object.assign(obj[extra.id_extra_tool], extra);
});

const extra_tools = [
{
    extra_tool_password: "tool data password",
    extra_tool_username: "tool data username",
    id_extra_tool: "8"
},
{
    extra_tool_password: "tool data password",
    extra_tool_username: "tool data username",
    id_extra_tool: "1"
},
{
    extra_tool_password: "tool data password",
    extra_tool_username: "tool data username",
    id_extra_tool: "7"
}
];


const extras = [
{
    extra_params: 1,
    extra_tool_name: "tool 1",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 1
},
{
    extra_params: 1,
    extra_tool_name: "tool 2",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 7
},
{
    extra_params: 0,
    extra_tool_name: "tool 3",
    extra_tool_password: "",
    extra_tool_username: "",
    id_extra_tool: 8
}
];

obj = {};
extra_tools.map((value) => {
obj[value.id_extra_tool] = value;
});

// iterate other array
const result = extras.map((extra) => {
return Object.assign(extra, obj[extra.id_extra_tool]);
});
console.log(result);

Related