3

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 an 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 overwrite
// e.g. const inputTitle = 'CCC'
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 overwrite
// e.g. const inputTitle = 'CCC'
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.

1
  • When you have working code and are asking for best practices, code style, mutability or performance considerations, then this is more suitable for Code Review Commented Mar 6, 2021 at 15:25

3 Answers 3

4

If this is a common use case that you will execute several times on the same data structure, then you are better off with a plain object keyed by title, as then the operation is trivial. You can still keep the title also as a property as you had it.

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

const title = 'AAA';
const people = ['Peter', 'Jane'];

data[title] = { title, people };  // yes, it's that simple then...

console.log(data);

If you really need the array structure, then you could consider to switch temporarily, then do all the manipulation, and then come back to the original format:

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

const title = 'AAA';
const people = ['Peter', 'Jane'];

// switch to other data structure...
let map = Object.fromEntries(data.map(o => [o.title, o]));

// Manipulate
map[title] = { title, people };

// ...and back:
data = Object.values(map);

console.log(data);

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

4 Comments

Oh my god I'm an idiot. This is such the obviously correct answer
But you are not the asker? Why would you say you're an idiot?
lol. Because the way I was trying to make it work was sooooooo hard and so cognitively taxing, and I spent awhile on it. When I saw your answer, it was immediately obvious that I had wasted much time and effort. I didn't even use your exact code - didn't even look at it really. As soon as I got your point, everything clicked.
Oh I see. Well, nice to hear it helped somehow! ;-)
1
let newdata = {title: 'AAA',people: [ 'Peter', 'Jane']}
//Create new object 

data.find(c => c.title === newdata.title) !== undefined 
// if title data from new object is find in old
? data.find(c => c.title === newdata.title).people=newdata.people
// change data
 : data.push(newdata)
// in not push it as new

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


let newdata = {title: 'AAA',people: [ 'Peter', 'Jane']}

data.find(c => c.title === newdata.title) !== undefined ? data.find(c => c.title === newdata.title).people=newdata.people : data.push(newdata)

console.log(data)

2 Comments

Here also it works if title exists but I want to push if it is a new title like for example CCC
@Álvaro See now
0

If only the matched items need to be updated, maybe a single forEach could solve this problem.

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

const inputTitle = 'AAA'
const inputPeople = ['Peter', 'Jane']

data.forEach(({ title }, index) => title === inputTitle ? data[index].people = inputPeople : null)

console.log(data)

1 Comment

Yes this works if the title exists, but not if the title is different like say CCC then it should push to it

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.