1

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

asked Jan 15, 2025 at 21:40
7
  • 1
    Correct, I need the new array to be created with the same name. I'm working in Svelte and for re-rendering reason I can't use push, for example. Commented Jan 15, 2025 at 21:48
  • 2
    Why would you need all that? I don't know your purpose, but it looks like you are creating an artificial data model for something that may not need it. Do you need unique name values? There are keyed collections for this purpose, such as JavaScript Map. Beware of the XY Problem. Commented Jan 15, 2025 at 21:59
  • 2
    Please use a Stack Snippet instead of a link to codesandbox. Commented Jan 15, 2025 at 22:03
  • 2
    @SergeyAKryukov I agree. The requirement seems like an XY-Problem. Also, having an array of say: [a1, a2, a3, a4] and if you remove a2, a3, and then you add a (as the Question is stating) the output would now be [a1, a4, a2] which is an extremely odd data output, specially given that those indexes (numbers) sequences seem important. I would instead (as a solution) rewrite all the indexes on every add/remove operation. Commented Jan 15, 2025 at 23:16
  • 1
    @Roko C. Buljan — "...an extremely odd data output..." Exactly! Commented Jan 15, 2025 at 23:21

2 Answers 2

2

addItem is adding suffixes to all the items that are already in the array. It should only append it to the new item you're adding.

So it should look for existing items that have the same name, or the same name with some suffix. It should add 1 to the highest of these.

In my code below I use a dynamically-generated regular expression to match the name with an optional suffix.

const addItem = (views, item) => {
 let name_regexp = new RegExp(`^${item.name}(?: (\\d+))?$`);
 let max_index = 0;
 views.forEach((obj) => {
 let match = obj.name.match(name_regexp);
 if (match) {
 let index;
 if (match[1]) {
 index = parseInt(match[1]);
 } else {
 index = 1;
 }
 if (index > max_index) {
 max_index = index;
 }
 }
 });
 if (max_index) {
 item.name += " " + (max_index + 1);
 }
 views.push(item);
};
addItem(views, {
 name: "A View",
 active: true,
});
addItem(views, {
 name: "A View",
 active: true,
});
addItem(views, {
 name: "A View",
 active: true,
});
console.log("views", views);
<script>
let views = [
 {
 name: "A View",
 active: true,
 },
 {
 name: "B View",
 active: false,
 },
 {
 name: "C View",
 active: false,
 }
];
</script>

answered Jan 15, 2025 at 22:23
Sign up to request clarification or add additional context in comments.

3 Comments

@dariusz ... The above one should be the accepted answer for it solves the described problem in an elegant and precise way. And precise refers to the coverage of all of the requirement's edge cases.
@PeterSeliger does this not fail to cover the requirements case where if a deletion of an existing index occurred, then that index should be available?
I missed that in the requirements. Filling in gaps is harder, I'll see if I have time to revise.
0

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,
});
answered Jan 15, 2025 at 22:05

4 Comments

this is exactly what I need. There is somer more functionalities I've mentioned in my post but it's OK as it is for now. I will try to figure out adding after deleting with the next "available" suffix.
btw @dariusz I'm not sure if I understood you correctly, but if we have A View, A View 3 and add a new item (assuming the previous A View 2 was deleted) then it should take up A View 2 here since we take the first available suffix.
Please explain what your solution actually does in a paragraph or two. "requirement" and "optimised" do not explain your take on the solution, which might be obvious to a seasoned developer, but not to others.
@SandilRanasinghe, yes, you are correct in thinking how delete/add should work with the first available suffix

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.