2

This is complicated to explain in words so let me just show you what I've got and work from there.

I have the following object:

{
  1: { name: 'Initial Step 1', stepNumber: 1 },
  2: { name: 'Initial Step 2', stepNumber: 2 },
  3: { name: 'Initial Step 3', stepNumber: 3 },
  4: { name: 'Initial Step 4', stepNumber: 4 },
}

I would like to perform a delete function for this step and then decreme the trailing keys so that I get the following outcome:

{
  1: { name: 'Initial Step 1', stepNumber: 1 },
  2: { name: 'Initial Step 3', stepNumber: 2 },
  3: { name: 'Initial Step 4', stepNumber: 3 },
};

I'm just not sure of the best way to implement my deleteStep function.

I've got it implemented as follows:

export const deleteStep = (stepNumber, steps) => {
    // What should I do here?
    return steps;
};

Thanks!

Barry Michael Doyle
  • 9,333
  • 30
  • 83
  • 143

4 Answers4

5

You could delete the actual key and check if more keys exists, then create a new property and delete the old reference.

function deleteAndShift(object, key) {
    delete object[key];
    while (++key in object) {
        object[key].stepNumber--;
        object[key - 1] = object[key];
        delete object[key];
    }
}

var object = { 1: { name: 'Initial Step 1', stepNumber: 1 }, 2: { name: 'Initial Step 2', stepNumber: 2 }, 3: { name: 'Initial Step 3', stepNumber: 3 }, 4: { name: 'Initial Step 4', stepNumber: 4 } };

deleteAndShift(object, 2);

console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • `while (key in object)`. Wow. Certainly looks like a syntax mistake on first glance :-) – Bergi Nov 02 '17 at 08:45
  • I would recommend to add a comment, or use a `for (; key in object; key++)` loop instead. – Bergi Nov 02 '17 at 08:45
  • I've edited your answer's `object` variable to match my question input and it doesn't reset the stepNumber inside each key object like I need it to. – Barry Michael Doyle Nov 02 '17 at 08:47
  • @BarryMichaelDoyle Well please don't edit your question to include new requirements. On the other hand, it should be quite trivial to add an assignment that changes the `.stepNumber` when moving the object to a new key. – Bergi Nov 02 '17 at 08:49
2

If you can/want to return a new object you can do the following:

const deleteStep = (stepNumber, steps) => {
    const result = {};
    Object.keys(steps).forEach(key => {
      key = Number(key);
      if (key < stepNumber) {
        // keep preceding entries
        result[key] = steps[key];
      } else if (key > stepNumber) {
        // shift following entries
        result[key - 1] = steps[key]; // or shallow copy with `Object.assign({}, steps[key])`
        result[key - 1].stepNumber--;
      }
    });
    return result;
};

const steps = {
  1: { name: 'Initial Step 1', stepNumber: 1 },
  2: { name: 'Initial Step 2', stepNumber: 2 },
  3: { name: 'Initial Step 3', stepNumber: 3 },
  4: { name: 'Initial Step 4', stepNumber: 4 },
};

console.log(deleteStep(3, steps));
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
1

You could go the immutable route and create a new object like this:

function omitStep (steps, stepNumber) {
  return Object.keys(steps).reduce(function (acc, key) {
    var keyNum = Number(key);
    if (keyNum < stepNumber) { 
      acc[key] = steps[key]
    } else if (keyNum > stepNumber) {
      acc[keyNum - 1] = steps[key];
    }
    
    return acc;
  }, {});
}

var newSteps = omitStep({
  1: { name: 'Initial Step 1', stepNumber: 1 },
  2: { name: 'Initial Step 2', stepNumber: 2 },
  3: { name: 'Initial Step 3', stepNumber: 3 },
  4: { name: 'Initial Step 4', stepNumber: 4 },
}, 3);

console.log(newSteps);
JLRishe
  • 99,490
  • 19
  • 131
  • 169
1

One possible solution is to use reduce
The advantage of reduce is that you return a new object and your old object didn't gets modified.

const removeStep = (steps, stepNumber) => {
  return Object.keys(steps).reduce((newSteps, current) => {
    const numberOfNewStep = Object.keys(newSteps).length + 1
    return Number(current) === stepNumber
      ? newSteps
      : Object.assign(
        {},
        newSteps, 
        { [numberOfNewStep]: Object.assign(
            {}, 
            steps[current], 
            {stepNumber: numberOfNewStep}
          )
        }
      )
  }, {})
}

console.log(removeStep({
  1: { name: 'Initial Step 1', stepNumber: 1 },
  2: { name: 'Initial Step 2', stepNumber: 2 },
  3: { name: 'Initial Step 3', stepNumber: 3 },
  4: { name: 'Initial Step 4', stepNumber: 4 },
}, 1))
Roman
  • 4,922
  • 3
  • 22
  • 31