TheWeeezel
TheWeeezel

Reputation: 361

Set new Sequence in Object from Array after deletion of specific object

My Goal: I need to have a continuous sequence of numbers in the sequenceIndex which is a value in my object.

So when I remove a specific object the sequence index of the other objects is of course not continuous anymore. The object I remove is being checked against a specific value to see whether there are other objects in the array which share the same value (second if-statement). If so then there should be a new value set which is continuous.

The output is that the iterator in the if-statement is always the same for all objects manipulated.

From this:

const objectsArray = [
  {
    folder: "folderName",
    documents: [
      {
        id: 0,
        sequenceIndex: "0",
        documentType: "letter"
      },
      {
        id: 1,
        sequenceIndex: "1",
        documentType: "letter"
      },
      {
        id: 2,
        sequenceIndex: "2",
        documentType: "letter"
      },
      {
        id: 3,
        sequenceIndex: "3",
        documentType: "letter"
      }
    ]
  }
];

By removing id 1 and 2 I would like to come to this (see continuous sequenceIndex):

const desiredObjectsArray = [
  {
    folder: "folderName",
    documents: [
      {
        id: 0,
        sequenceIndex: "0",
        documentType: "letter"
      },
      {
        id: 3,
        sequenceIndex: "1",
        documentType: "letter"
      }
    ]
  }
];

My code so far:

case ActionType.RemoveDocumentInSpecificFolder:
        return state.map(file => {
          // if in the correct folder remove the object with the delivered id
          if (file.folder=== folder) {
            remove(file.documents, {
              id: action.payload.documents[0].id
            });

            // create newObjArray from objects which share a specific value and replace the sequence index by new value
            const newObjArray = file.documents.map((obj: any) => {
              // if the object has the specific value create new object with new sequenceIndex
              if (obj.documentType === action.payload.documents[0].documentType) {

                //poor attempt to create a sequence
                let i = 0;
                const correctedSequenceDocObject = { ...obj, sequenceIndex: i };
                i++;
                return correctedSequenceDocObject;

              }
              return {
                ...obj
              };
            });
                return {
              ...file,
              documents: newObjArray
            };
          }
          return file;
        });

I hope someone can guide me in the right direction. I would also always appreciate a suggestion of best practice :)

Best regards

Upvotes: 0

Views: 448

Answers (3)

TheWeeezel
TheWeeezel

Reputation: 361

The solution I used now to this problem was:

            let count = 0;
            const newObject = file.documents.map(obj => {
              if (obj.documentType === firstDocument.documentType) {
                count++;
                return { ...obj, sequenceIndex: count - 1 };
              }
              return obj;
            });

Both of the provided answers were not able to handle objects which were out of interest because of the different documentType so they dropped the object. with this solution, I am checking against the last element and increasing the count if the last element was the same documentType.

Upvotes: 0

Rajesh
Rajesh

Reputation: 24945

As commented:

This is the classic case where .filter().map() will be useful. filter the data and then use .map((o, i) => ({ ...obj, sequenceIndex: i+1 }) )

Following is the sample:

const objectsArray = [{
  folder: "folderName",
  documents: [{
      id: 0,
      sequenceIndex: "0",
      documentType: "letter"
    },
    {
      id: 1,
      sequenceIndex: "1",
      documentType: "letter"
    },
    {
      id: 2,
      sequenceIndex: "2",
      documentType: "letter"
    },
    {
      id: 3,
      sequenceIndex: "3",
      documentType: "letter"
    }
  ]
}];
const ignoreIds = [1, 2]
const updatedDocs = objectsArray[0].documents
  .filter(({
    id
  }) => !ignoreIds.includes(id))
  .map((doc, index) => ({ ...doc,
    sequenceIndex: index
  }));

console.log(updatedDocs)


Now lets cover your attempt

const newObjArray = file.documents.map((obj: any) => {
  // For all the unmatching objects, you will have undefined as object as you are using `.map`
  // This will make you `newObjArray: Array<IDocument | undefined>` which can break your code.
  if (obj.documentType === action.payload.documents[0].documentType) {

    // This will set it as 0 in every iteration making i as 0 always.
    let i = 0;
    const correctedSequenceDocObject = { ...obj, sequenceIndex: i };
    i++;
    return correctedSequenceDocObject;

  }
  return { ...obj };
});

An alternate with single loop:

Idea:

  • Create a loop using Array.reduce and pass it a blank array as list.
  • Add a check and inside it, push value to this list.
  • For sequenceIndex, fetch last element and fetch its sequenceIndex. Add one and set it again.
const newObjArray = file.documents.reduce((acc: Array<IDocument>, obj: any) => {
  if (obj.documentType === action.payload.documents[0].documentType) {
    const sequenceIndex: number = (!!acc[acc.length - 1] ? acc[acc.length - 1].sequenceIndex : 1) + 1;
    acc.push({ ...obj, sequenceIndex });
  }
  return acc;
});

Upvotes: 1

Code Maniac
Code Maniac

Reputation: 37755

You can use filter and map something like this

const arr = [{folder: "folderName",documents: [{id: 0,sequenceIndex: "0",documentType: "letter"},{id: 1,sequenceIndex: "1",documentType: "letter"},{id: 2,sequenceIndex: "2",documentType: "letter"},{id: 3,sequenceIndex: "3",documentType: "letter"}]}];

let getInSequence = (filterId) => {
  return arr[0].documents.filter(({ id }) => !filterId.includes(id))
               .map((v, i) => ({ ...v, sequenceIndex: i }))
}

console.log(getInSequence([1, 2]))

Upvotes: 1

Related Questions