1

I have 2 arrays,

let array1 = ["1", "2", "3"]

let array2 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]

I want to replace the contents of array1 with elements of array2 when array1 element and array2 id element's value matches. Result should be something like this:

array1 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}]

I know I can get the result in a separate array, but I want to replace the contents of array1 without having to create a new array.

I tried this:

array1.splice(0, Infinity, ...array2)

based on an answer given to a similar question here

This results in:

array1 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]

I tried different ways to add a condition to this statement but failed. Is there a way to add a condition to the splice method above? Or if there is a better way of achieving it, do suggest.

4 Answers 4

2

You could also search for the array2 ids in array1 then replace array1's indices with the matching array2 indices.

let array1 = ["1", "2", "3"]

let array2 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]

array2.forEach(function(e){
    if(array1.indexOf(e["id"]) != -1) {
        array1[array1.indexOf(e["id"])] = e
    }
})

console.log(array1)

EDIT: I tried a different approach by mapping each values in array1 with comparing values of array2 ids in filter, I don't think if it's a cleaner solution but I tried:

let array1 = ["1", "2", "3"]

let array2 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]

array1 = array1.map(num => {
  return array2.filter(dict => {
    if(dict["id"] == num) {return dict}
  })[0]
})

console.log(array1)

If you can use lodash, it is pretty short:

let array1 = ["1", "2", "3"]

let array2 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]

array1 = _.map(array1, function(o){return _.find(array2, {id: o})})

console.log(array1)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Sign up to request clarification or add additional context in comments.

2 Comments

There must be a shorter way of achieving this without having to loop through the array ?
I updated the answer with two more methods in order that any of them complies with you. The answer sent by @StepUp below looks like the answer you are looking for.
1

We can use keyed collection - Map to get items by key.

const array1 = ["1", "2", "3"]

const array2 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]

const array2Map = new Map(array2.map(o=> [o.id, o]));

const result = array1.map(o => ({
  ...array2Map.get(o)
}));
console.log(result);

In addition, you can use filter and some methods to achieve desired result:

let array1 = ["1", "2", "3"]

let array2 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]       

array1 = array2.filter(f=> array1.some(s=> s == f.id));

console.log(array1);

Another way, however more verbose and not optimal:

let array1 = ["1", "2", "3"]

let array2 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]       

array1 = array1.map(a => {
    let obj = array2.find(a2=> a2.id == a);
    if (obj) return obj;
    return a;
})

console.log(array1);

Comments

1

Looks like Array.filter will do the job?

let array1 = ["1", "2", "3"];
array1 = [
  {"name": "a", "id" : "1"}, 
  {"name": "b", "id" : "2"}, 
  {"name": "c", "id" : "3"}, 
  {"name": "c", "id" : "4"}
].filter(v => array1.includes(v.id));

// using Array.indexOf (IE >= 9, nodejs all versions), 
let array2 = ["1", "2", "3"];
array2 = [
  {"name": "a", "id" : "1"}, 
  {"name": "b", "id" : "2"}, 
  {"name": "c", "id" : "3"}, 
  {"name": "c", "id" : "4"}
].filter(v => array2.indexOf(v.id) > -1);

console.log(array1);
console.log(array2);

4 Comments

this works but includes isn't supported by internet explorer and and also not supported for node.js versions below 6.0.0 according to this.
If browser (or even nodejs) compatibility is really an issue, you can use the polyfill (developer.mozilla.org/nl/docs/Web/JavaScript/Reference/…)
@hushie you could have mentioned the compatibility requirement in the question
@Kooilnc I should have, I missed it.
1

let array1 = ["1", "2", "3"]

let array2 = [{"name": "a", "id" : "1"}, {"name": "b", "id" : "2"}, {"name": "c", "id" : "3"}, {"name": "c", "id" : "4"}]       

array1 = array2.filter(f=> array1.find(s=> s == f.id));

console.log(array1);

/**outPut :[
  {
"name": "a",
"id": "1"
  },
  {
"name": "b",
"id": "2"
  },
  {
"name": "c",
"id": "3"
  }
]**/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.