Reputation: 107
I am developing an E-Commerce using Javascript. In the section of the products of the page, I want to implement the functionality to change the order of the products setting the number in the corresponding input. You can see an image to get an idea of the interface.
The algorithm I looking for has to reorder all the products if the user changes the input of the Orden column.
For example:
If the user sets a value that already exists, the product will place below the product that already has the position entered. The position values are always multiple of 10.
The data is structured in an ArrayList that contains the product reference and its position: Its name is lista_variantes.
0: {numero: "0003-0007", posicion: 10}
1: {numero: "0003-0006", posicion: 20}
2: {numero: "0003-0004", posicion: 30}
3: {numero: "0003-0008", posicion: 40}
4: {numero: "0003-0014", posicion: 50}
5: {numero: "0003-0016", posicion: 60}
6: {numero: "0003-0017", posicion: 70}
7: {numero: "0003-0018", posicion: 80}
And then using this map, I update the Database and read the product information in the correct order. I have implemented correctly this, I only want the algorithm to achieve the example behaviour.
Upvotes: 1
Views: 443
Reputation: 35243
map
the array of objects and add a new property called isUpdated
which checks if the posicion
is same based on the index.sort
the array based on posicion
. If 2 items have the same posicion
, then sort them based on isUpdated
propertymap
the array again to remove the isUpdated
property and get the posicion
values based on their indexconst map = [
{ numero: "0003-0007", posicion: 10 },
{ numero: "0003-0006", posicion: 20 },
{ numero: "0003-0004", posicion: 30 },
{ numero: "0003-0008", posicion: 25 }, //-- updated
{ numero: "0003-0014", posicion: 20 }, //-- updated
{ numero: "0003-0016", posicion: 60 }
]
const output = map.map((o, i) => ({ ...o, isUpdated: (i+1) * 10 !== o.posicion }))
.sort((a,b) => a.posicion - b.posicion || a.isUpdated - b.isUpdated)
.map(({ isUpdated, ...rest }, i) => ({ ...rest, posicion: (i+1) * 10 }))
console.log(output)
It would be better if you have another property to keep the posicion
value before update or an onchange event which updates the isUpdated
proeprty. If you have that, you can skip the step where you check whether the object has been updated or not.
Here's a snippet using for loop and some comments
const map = [
{ numero: "0003-0007", posicion: 10 },
{ numero: "0003-0006", posicion: 20 },
{ numero: "0003-0004", posicion: 30 },
{ numero: "0003-0008", posicion: 25 }, //-- updated
{ numero: "0003-0014", posicion: 20 }, //-- updated
{ numero: "0003-0016", posicion: 60 }
]
// add isUpdated property and set it to true if posicion is not equal to (i+1) * 10
for (let i = 0; i < map.length; i++) {
const o = map[i];
o.isUpdated = (i+1) * 10 !== o.posicion
}
// sort based on posicion
// if both have the same posicion, the subtraction returns 0
// so, || will check the next condition
// Sorting based on boolean: https://stackoverflow.com/a/54826593
map.sort((a,b) => a.posicion - b.posicion || a.isUpdated - b.isUpdated);
// delete the isUpdated property
// update the posicion based on the new index
for (let i = 0; i < map.length; i++) {
const o = map[i];
o.posicion = (i+1) * 10;
delete o.isUpdated
}
console.log(map)
Upvotes: 2