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.

Nazim Kerimbekov
  • 4,712
  • 8
  • 34
  • 58
hushie
  • 417
  • 10
  • 23

4 Answers4

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/lodash@4.17.15/lodash.min.js"></script>
Guven Degirmenci
  • 684
  • 7
  • 16
  • There must be a shorter way of achieving this without having to loop through the array ? – hushie Nov 23 '19 at 10:26
  • 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. – Guven Degirmenci Nov 23 '19 at 11:08
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);
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • 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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes). – hushie Nov 23 '19 at 10:23
  • If browser (or even nodejs) compatibility is really an issue, you can use the polyfill (https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill) – KooiInc Nov 23 '19 at 11:13
  • 1
    @hushie you could have mentioned the compatibility requirement in the question – KooiInc Nov 23 '19 at 11:29
  • @Kooilnc I should have, I missed it. – hushie Nov 25 '19 at 06:17
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);
StepUp
  • 36,391
  • 15
  • 88
  • 148
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"
  }
]**/
Jadli
  • 858
  • 1
  • 9
  • 17