Home > Software design >  Reordering version dotted serial number array of objects
Reordering version dotted serial number array of objects

Time:09-20

I have data in an array of obj with versioning dotted serial numbers like below

var sampleData = [
  { name: 'Edward', serialNumber: '1' },
  { name: 'Sharpe', serialNumber: '1.1' },
  { name: 'And', serialNumber: '1.2' },
  { name: 'The', serialNumber: '1.2.1' },
  { name: 'Magnetic', serialNumber: '2' },
  { name: 'Zeros', serialNumber: '2.1' },
  { name: 'Zeros', serialNumber: '2.1.1' },
  { name: 'shappa', serialNumber: '3' },
  { name: 'Firo', serialNumber: '4' },
  { name: 'Dholya', serialNumber: '4.1' },
  { name: 'dhampya', serialNumber: '4.1.1' },
  { name: 'SHivaji', serialNumber: '4.2' },
  { name: 'Jyoti', serialNumber: '4.2.1' },
  { name: 'Shr', serialNumber: '4.2.2' }
];

In the above sample data if the user removes the serial number 3 then the array should be.

 var sampleData = [
  { name: 'Edward', serialNumber: '1' },
  { name: 'Sharpe', serialNumber: '1.1' },
  { name: 'And', serialNumber: '1.2' },
  { name: 'The', serialNumber: '1.2.1' },
  { name: 'Magnetic', serialNumber: '2' },
  { name: 'Zeros', serialNumber: '2.1' },
  { name: 'Zeros', serialNumber: '2.1.1' },
  { name: 'Firo', serialNumber: '3' },
  { name: 'Dholya', serialNumber: '3.1' },
  { name: 'dhampya', serialNumber: '3.1.1' },
  { name: 'SHivaji', serialNumber: '3.2' },
  { name: 'Jyoti', serialNumber: '3.2.1' },
  { name: 'Shr', serialNumber: '3.2.2' }
];

here we just reordered the object 4, 4.1, 4.1.1, 4.2, 4.2.1, 4.2.2 serial number objects to 3, 3.1, 3.1.1, 3.2, 3.2.1, 3.2.2


If the user removes the 4 serialNumber objects then all 4 children should be removed like the above original array will be.

var sampleData = [
  { name: 'Edward', serialNumber: '1' },
  { name: 'Sharpe', serialNumber: '1.1' },
  { name: 'And', serialNumber: '1.2' },
  { name: 'The', serialNumber: '1.2.1' },
  { name: 'Magnetic', serialNumber: '2' },
  { name: 'Zeros', serialNumber: '2.1' },
  { name: 'Zeros', serialNumber: '2.1.1' },
  { name: 'shappa', serialNumber: '3' }
];

If the user removes the 4.1 serialNumber objects then 4.1 & 4.1 children will get removed from the list and 4.2 & his children will become 4.1 & his childer like below.

var sampleData = [
  { name: 'Edward', serialNumber: '1' },
  { name: 'Sharpe', serialNumber: '1.1' },
  { name: 'And', serialNumber: '1.2' },
  { name: 'The', serialNumber: '1.2.1' },
  { name: 'Magnetic', serialNumber: '2' },
  { name: 'Zeros', serialNumber: '2.1' },
  { name: 'Zeros', serialNumber: '2.1.1' },
  { name: 'shappa', serialNumber: '3' },
  { name: 'Firo', serialNumber: '4' },
  { name: 'SHivaji', serialNumber: '4.1' },
  { name: 'Jyoti', serialNumber: '4.1.1' },
  { name: 'Shr', serialNumber: '4.1.2' }
];

is there any best way to do this, reorder the above list if any object gets removed.

CodePudding user response:

This is a bit trickier than I would have thought to implement. I think if I was faced with this problem, I would rethink how I was storing the data because dynamically renumbering possibly all pieces of data anytime you add or remove an item is a lot of real-time maintenance. A more scalable solution would be to create a hierarchical data structure where you represent the depth of serialNumber in the data structure itself without manually numbering things. At any point in time, you can generate a serialNumber for a given item by just looking at it's position in the hierarchy. But, when you modify the data structure, you don't have to regenerate or renumber all the serialNumbers. That would be a more scalable solution and would probably perform better (depending upon the mix of operations you're doing on the structure).

Anyway, here's an implementation that meets your rules. It has these steps:

  1. Get the target item being removed.
  2. Starting at that point in the array, count how many "child" serial numbers that also have to be removed with it are present.
  3. Remove the target and any children from the array.
  4. Starting at the point of deletion in the array, see how many items must be renumbered by comparing to see which items match the start of the deleted item

var sampleData = [
    { name: 'Edward', serialNumber: '1' },
    { name: 'Sharpe', serialNumber: '1.1' },
    { name: 'And', serialNumber: '1.2' },
    { name: 'The', serialNumber: '1.2.1' },
    { name: 'Magnetic', serialNumber: '2' },
    { name: 'Zeros', serialNumber: '2.1' },
    { name: 'Zeros', serialNumber: '2.1.1' },
    { name: 'shappa', serialNumber: '3' },
    { name: 'Firo', serialNumber: '4' },
    { name: 'Dholya', serialNumber: '4.1' },
    { name: 'dhampya', serialNumber: '4.1.1' },
    { name: 'SHivaji', serialNumber: '4.2' },
    { name: 'Jyoti', serialNumber: '4.2.1' },
    { name: 'Shr', serialNumber: '4.2.2' }
];

// break 'x.y.z' string into numeric pieces in an array [x.y.z]
function parseDotNumber(str) {
    const pieces = str.split(".");
    return pieces.map(piece => parseInt(piece, 10))
}

// join numeric array [x,y,z] back into 'x.y.z' string
function joinDotNumber(pieces) {
    return pieces.map(num => num.toString()).join(".");
}

function removeItem(data, index) {
    const targetItem = data[index];
    const targetMatch = targetItem.serialNumber   ".";
    let numToRemove = 1;
    // now remove any other elements following that match the deleted part
    for (let i = index   1; i < data.length; i  ) {
        if (data[i].serialNumber.startsWith(targetMatch)) {
              numToRemove;
        } else {
            break;
        }
    }
    // remove all the matching items we found
    data.splice(index, numToRemove);

    // now renumber any following pieces that have the same origin as the target
    const targetPieces = parseDotNumber(targetItem.serialNumber);

    // make copy of the array that just removes the last item
    const originPieces = targetPieces.slice(0, -1);
    let originStr = joinDotNumber(originPieces);
    // if it's not top level, make sure we're matching the whole number by appending a "."
    if (originStr) originStr  = ".";

    // so any serialNumber that starts with originStr needs to be renumbered
    // by incrementing the [originPieces.length] digit

    for (let i = index; i < data.length; i  ) {
        const serialNum = data[i].serialNumber;
        if (!originStr || serialNum.startsWith(originStr)) {
            let pieces = parseDotNumber(serialNum);
            --pieces[originPieces.length];
            data[i].serialNumber = joinDotNumber(pieces);
        } else {
            break;
        }
    }
    return data;
}

function test(index) {
    // make a deep copy of the sampleData
    const data = JSON.parse(JSON.stringify(sampleData));
    const result = removeItem(data, index);
    console.log("Removing", JSON.stringify(sampleData[index]));
    console.log("Result is [");
    for (let item of data) {
        console.log("   ", JSON.stringify(item));
    }
    console.log("]");
}


// run tests starting at multiple different spots
test(7);    // 3
test(8);    // 4
test(9);    // 4.1

  • Related