Add / Overwrite an object in an array

Posted on

Problem

I am trying to overwrite an object in an array if the title property exists, otherwise just push it to the array. I found two approaches and I wonder which one is the preferred one.

Performance is not really and issue but I wonder whether mutability could be, or just there is a better way to do this altogether.

On this snippet I am using a for loop to edit the original array:

const data = [
  {
    title: 'AAA',
    people: [ 'John', 'Megan',]
  },{
    title: 'BBB',
    people: [ 'Emily', 'Tom']
  }
]

// If inputTitle is not on any of data's title it will append not overwritte
const inputTitle = 'AAA'
const inputPeople = ['Peter', 'Jane']

for (const obj of data) {
  if (obj.title === inputTitle) {
    obj.people = inputPeople
    break
  } else {
    data.push({
      title: inputTitle,
      people: inputPeople
    })
    break
  }
}

console.log(data)

Here I am using high order functions and spread to do the same:

const data = [
  {
    title: 'AAA',
    people: [ 'John', 'Megan',]
  },{
    title: 'BBB',
    people: [ 'Emily', 'Tom']
  }
]

// If inputTitle is not on any of data's title it will append not overwritte
const inputTitle = 'AAA'
const inputPeople = ['Peter', 'Jane']

let res = []

if (data.some(({ title }) => title === inputTitle)) {
  res = data.map(obj => {
    if (obj.title === inputTitle) 
      obj.people = inputPeople
    return obj
  })
} else {
  res = [...data, { title: inputTitle, people: inputPeople}]
}

console.log(res)

In the real task I am reading the data array from a json file with node and writing the changes back to it.

Solution

From a short review;

  • The first snippet does not work, try it with inputTitle = 'BBB'

  • You are in essence doing 2 things

    1. Find a possible match
    2. Update the match or insert the data

    Ideally, this is done in 1 ‘loop’

  • If you don’t care too much about performance, I would go for a functional approach

This is my counter-proposal (which modifies the data)

const data = [
  {
    title: 'AAA',
    people: [ 'John', 'Megan',]
  },{
    title: 'BBB',
    people: [ 'Emily', 'Tom']
  }
]

function mergePeople(data, title, people){
  const target = data.filter(record=>record.title===title);
  if(target.length){
    target.forEach(record => record.people = people);
  }else{
    data.push({title, people});
  }
  return data;
}

function quickClone(o){
  return JSON.parse(JSON.stringify(o));
}

console.log(mergePeople(quickClone(data), "AAA", ["Tom", "Jerry"]));
console.log(mergePeople(quickClone(data), "BBB", ["Ben", "Jerry"]));

Leave a Reply

Your email address will not be published. Required fields are marked *