exc22
exc22

Reputation: 51

javascript - map with conditionally altered nested field

Given an array such as:

people = [
    {
        name: 'Bob',
        sex: 'male',
        address:{
          street: 'Elm Street',
          zip: '12893'
        }
    },
    {
        name: 'Susan',
        sex: 'female',
        address:{
          street: 'Hickory Street',
          zip: '00000'
        }
    }
]

I am trying to write a function which will alter specific instances of '00000' in the nested field 'zip' to the string '12893' and return a new array identical to the initial array except with the corrected values. My attempt at a function so far is:

function zipFix (initialArray) {
    return initialArray.map(function(person) {
        if(person.address.zip === '00000')
          person.address.zip = "12893"
        return person
    });
}

I know this function is altering the values in 'initialArray', which isn't supposed to happen. How can I go about writing my function so that I can effectively use the map function to create a new, corrected array? Thanks.

Upvotes: 2

Views: 815

Answers (4)

Yosvel Quintero
Yosvel Quintero

Reputation: 19080

You can do:

const people = [{name: 'Bob',sex: 'male',address: {street: 'Elm Street',zip: '12893'}},{name: 'Susan',sex: 'female',address: {street: 'Hickory Street',zip: '00000'}}]
const zipFix = people.map(({address, ...p}) => ({
  ...p,
  address: {
    ...address,
    zip: address.zip === '00000' ? '12893' : address.zip
  }
}))

console.log(zipFix)

Upvotes: 1

ray
ray

Reputation: 27275

people = [{
    name: 'Bob',
    sex: 'male',
    address: {
      street: 'Elm Street',
      zip: '12893'
    }
  },
  {
    name: 'Susan',
    sex: 'female',
    address: {
      street: 'Hickory Street',
      zip: '00000'
    }
  }
]

function zipFix (initialArray) {
  return (initialArray.map(({address, ...p}) => (
    address.zip !== '00000' ? { ...p, address } : {
      ...p,
      address: {
        ...address,
        zip: '12893'
      }
    }
  )));
}

console.log(zipFix(people));

Upvotes: 2

Code Maniac
Code Maniac

Reputation: 37755

You need to return values from callback function too, also make a copy of element before assigning to avoid mutability

const people = [{name: 'Bob',sex: 'male',address:{street: 'Elm Street',zip: '12893'}},{name: 'Susan',sex: 'female',address:{street: 'Hickory Street',zip: '00000'}}]

function zipFix (initialArray) {
    return initialArray.map(function(person) {
      let newObj = JSON.parse(JSON.stringify(person))
        if(newObj.address.zip === '00000')
           newObj.address.zip ="12893"
      return newObj
    });
}

console.log(zipFix(people))

Upvotes: 2

skovy
skovy

Reputation: 5650

While map-ing over the values, you will need to create a copy of each object. The easiest way to do so is with the object spread syntax ({...obj}).

This will "spread" all the values (name, adress, etc) into a new object. So any changes won't mutate it. However, it's "shallow" meaning it will be a new object but its values are the same. So since address is also an object we need to copy that as well, hence the reason for the nested spread of the address value as well.

people = [{
    name: 'Bob',
    sex: 'male',
    address: {
      street: 'Elm Street',
      zip: '12893'
    }
  },
  {
    name: 'Susan',
    sex: 'female',
    address: {
      street: 'Hickory Street',
      zip: '00000'
    }
  }
]

function zipFix(initialArray) {
  return initialArray.map(function(person) {
    // Create a new "copy" of the person. Using object spread
    // will create a "shallow" copy, so since address is also an
    // object it will have to be spread (same for other objects that might
    // be mutated).
    const newValue = { ...person, address: { ...person.address }}

    if (newValue.address.zip === '00000') {
      newValue.address.zip = "12893";
    }

    return newValue
  });
}

console.log(zipFix(people))
console.log(people) // unchanged

Upvotes: 2

Related Questions