Search code examples
javascriptprefixsuffix

How to add a suffix to duplicates array of objects using javascript?


I've got a following array of objects

let views = [
  {
    name: "A View",
    active: true,
  },
  {
    name: "B View",
    active: false,
  },
  {
    name: "C View",
    active: false,
  }
];

When another elements are added, one by one with the existing name, for example another "A View", and another "A View" like for example

{
  name: "A View",
  active: true,
}

I want to add the suffix number to the name in the counting order, so I've got

[
  {
    name: "A View",
    active: true,
  },
  {
    name: "B View",
    active: false,
  },
  {
    name: "C View",
    active: false,
  },
  {
    name: "A View 2",
    active: true,
  }
]

after the first new "A View" added

And

[
  {
    name: "A View",
    active: true,
  },
  {
    name: "B View",
    active: false,
  },
  {
    name: "C View",
    active: false,
  },
  {
    name: "A View 2",
    active: true,
  },
  {
    name: "A View 3",
    active: true,
  }
];

after the second "A View" element added, and so on... Is I then remove "A View 2" I want the "2" suffix to be available to add for the new "A view" if I add it. So the next "A View" item will be "A View 2", not "A View 4"

This is my current solution

const addItem = (item) => {
  views = [...views, item];
  let names = {};

  views.forEach((obj) => {
    if (names[obj.name]) {
      obj.name += " " + ++names[obj.name];
    } else {
      names[obj.name] = 1;
    }
  });

  console.log("views", views);
};

The problem is that the suffix is not adding correctly. If I call the function 3 times passing the same object, like for example

addItem({
  name: "A View",
  active: true,
});

I will have this

enter image description here

Here is the working example - https://codesandbox.io/p/sandbox/8dhpl3


Solution

  • This seems to cover your requirement, although perhaps it can be optimised a little more.

    Here, if a name or suffix exists, we iterate through the possible suffixes in ascending order until we get one that doesn't exist. For example, if A View and A View 2 are already in views, we keep incrementing our suffix counter until we reach A View 3 which is available.

    Note that even if we delete one in the middle, say the second one, leaving us with [A View, A View 3, A View 4], we still fill A View 2 as required since we take the first available suffix.

    let views = [
      {
        name: "A View",
        active: true,
      },
      {
        name: "B View",
        active: false,
      },
      {
        name: "C View",
        active: false,
      },
    ];
    
    const addItem = (item) => {
      let names = {};
    
      views.forEach((obj) => {
          names[obj.name] = 1;
      });
      
      let _suffix = "";
      let _suffix_ctr = 1;
      while (names[item.name + _suffix]) {
          _suffix_ctr++;
          _suffix = " " + _suffix_ctr;
      }
      
      let new_name = item.name + _suffix;
      views = [...views, {...item, name: new_name}]
    
      console.log("views", views);
    };
    
    addItem({
      name: "A View",
      active: true,
    });
    
    addItem({
      name: "A View",
      active: true,
    });
    
    addItem({
      name: "A View",
      active: true,
    });