1

I have an array that is defined like this:

const arr = [
  {
    status: 'status1',
    count: 2,
    elements: [
      {
        id: '1',
      },
      {
        id: '2',
      },
    ],
  },
  {
    status: 'status2',
    count: 1,
    elements: [
      {
        id: '3',
      },
    ],
  },
  {
    status: 'status3',
    count: 1,
    elements: [
      {
        id: '4',
      },
    ],
  },
];

The array is dynamic, but I know the status field and the id inside the elements. What I am trying to achieve is a new array, that contains all the same items, but looks like this instead:

const arr = [
  {
    status: 'status1',
    count: 1,
    elements: [
      {
        id: '1',
      },
    ],
  },
  {
    status: 'status2',
    count: 2,
    elements: [
      {
        id: '2',
      },
      {
        id: '3',
      },
    ],
  },
  {
    status: 'status3',
    count: 1,
    elements: [
      {
        id: '4',
      },
    ],
  },
];

In other words, if status === status1, remove element with id === 2, set count to the length of elements array (or decrease by 1), take the element that has id === 2 and put it into elements array that has status === status2, set total count to the length of elements array .

I am not all that strong with iterating through nested elements and manipulating the array in these ways, but simpler concepts with array.filter/map etc seems okay, but I cannot wrap my head around all of this. :P

I would prefer to use vanilla JS, if possible. But I do have access to lodash if it makes things a lot easier.


Edit: When I mean vanilla JS, I refer to not using a ton of external libraries, but ES6 is what I use at this project.

My try consists of simply trying to filter arr on status, and then again on my id. Then I know what item I want to move. But it kind of stops there, and I also believe that it could be much more efficient:

const itemToMove = arr.filter(e => e.status === "status1")[0].elements.filter(e => e.id ==='2' )

I am not sure how to best proceed after this, thus asking for help.

3
  • at least, you could add your try ... Commented Mar 31, 2021 at 8:27
  • Where is the code that shows that you have tried to solve this yourself which we can improve upon? Also, when you say vanilla JS which version of ECMAS script do you consider vanilla? Commented Mar 31, 2021 at 8:29
  • I have edited my answer, but as I am not sure how to solve it, and I also belive that my filter().filter() could be much improved, I did not want to include it. Commented Mar 31, 2021 at 8:39

1 Answer 1

2

You could find the source and target objects and splice the element.

const
    move = (data, from, to, id) => {
        const
            find = value => ({ status }) => status === value,
            source = data.find(find(from)),
            target = data.find(find(to)),
            index = source.elements.findIndex(o => o.id === id);
            
        if (index === -1) return;
        
        target.elements.push(...source.elements.splice(index, 1));
        source.count--;
        target.count++;
    },
    array = [{ status: 'status1', count: 2, elements: [{ id: '1' }, { id: '2' }] }, { status: 'status2', count: 1, elements: [{ id: '3' }] }, { status: 'status3', count: 1, elements: [{ id: '4' }] }];
   

move(array, 'status1', 'status2', '2');
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this does exactly what I asked for. It does also edit the original array, and my usecase cannot modify the original array, but I belive I can find a solution for that :) Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.