How to update sequence property of an object if it's order is changing inside another object?

Viewed 135

So I have an object of objects where each inside object has it is own seq property which points at it's order inside the big object.

Example:

const obj = {
  '1': {
    name: 'apple',
    seq: 1,
    id: 1,
  },
  '2': {
    name: 'orange',
    seq: 2,
    id: 2,
  },
  '3': {
    name: 'banana',
    seq: 3,
    id: 3,
  },
}

My goal is to move these objects around and update their seq accordingly.

For example

const obj = {
  '1': {
    name: 'apple',
    seq: 1,
    id: 1,
  },
  '3': {
    name: 'banana',
    seq: 2,
    id: 3,
  },
  '2': {
    name: 'orange',
    seq: 3,
    id: 2,
  },
}

I know the id of the object I'm moving and to which position it is moving

What I have so far

const moveObjects = (objId, indexToMoveTo) => {
  const objCopy = Object.values(obj).reduce((prev, curr) => {
    // if element if the one we moved - set seq to index
    if (curr.id === objId) {
      prev[curr.id] = {
        ...curr,
        seq: indexToMoveTo
      };
    } else if (curr.id !== objId) {
      // if element is not the one and index is smaller - increase seq by one
      if (curr.seq >= indexToMoveTo) {
        prev[curr.id] = {
          ...curr,
          seq: curr.seq + 1
        };
      }
      // if index bigger than seq - return the element without modifying it
      else if (curr.seq < indexToMoveTo) {
        prev[curr.id] = {
          ...curr
        };
      }
    }
    return prev;
  }, {})
  return objCopy
}

The problem with this is that of course if you move an element around a few times seq starts to increase beyond the length of the object, it can become 4, 5, 6 for example.

Here is the link to the jsfiddle to see more clearly what I mean. (the third console.log)

All the help to resolve this will be much appreciated

2 Answers

Why are you not just use an array, then you don't need to use Object.values and also you have access to the index whenever you want, no need to store the seq inside of your objects.

For the objects to actually change position you have to change the key since the keys in an object are sorted by default.

Here is a different approach

const obj = { '1': { name: 'apple', seq: 1, id: 1, }, '2': { name: 'orange', seq: 2, id: 2, }, '3': { name: 'banana', seq: 3, id: 3, }, }
const moveObjects = (objId, indexToMoveTo) => {
 arr= Object.entries(obj)
 tobj=arr.filter(o => o[1].id == objId).flat()
 tobj[1].seq = indexToMoveTo ,temp = tobj[0]
 tobj[0] = indexToMoveTo
 k = arr.splice(temp - 1, 1)
 arr.splice(indexToMoveTo-1, 0, k[0]);
arr.forEach((o,i)=>{o[1].seq = i+1, o[0] = i+1})
map=new Map([...arr])
 return Object.fromEntries(map)
}
console.log(moveObjects(3, 2))
console.log(moveObjects(1, 3))

if you want to keep the keys the same but only change the seq you could use the same code without modifying the keys however the objects will remain in the same place

const obj = { '1': { name: 'apple', seq: 1, id: 1, }, '2': { name: 'orange', seq: 2, id: 2, }, '3': { name: 'banana', seq: 3, id: 3, }, }

 arr= Object.entries(obj)
const moveObjects = (objId, indexToMoveTo) => {
 arr= Object.entries(obj)
 tobj=arr.filter(o=>o[1].id==objId).flat()
 tobj[1].seq=indexToMoveTo ,temp=tobj[0]
 tobj[0]=indexToMoveTo
 k=arr.splice(temp-1,1)
 arr.splice(indexToMoveTo-1, 0, k[0]);
arr.forEach((o,i)=>{o[1].seq=i+1})
map=new Map([...arr])
 return Object.fromEntries(map)
}
console.log(moveObjects(3, 2))

Related