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
Here is the working example - https://codesandbox.io/p/sandbox/8dhpl3
2 Answers 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>
3 Comments
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,
});
4 Comments
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.
namevalues? There are keyed collections for this purpose, such as JavaScriptMap. Beware of the XY Problem.[a1, a2, a3, a4]and if you removea2, a3, and then you adda(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 everyadd/removeoperation.