Reverse object hierarchy

Viewed 441

is there any way to reverse the object in js?

wanna make a function, but struggling hard. I tried to find the object depth-first and then make a founded amount of iterations for .. in .. inside the object but don't know how to rewrite the new one

const initObject = { 
  value: 5,
  next: {
   value: 10,
   next: {
     value: 15
     next: null
   }
  },
}

//expected result

const newObject = {
  value: 15,
  next: {
    value: 10,
    next: {
      value: 5,
      next: null
    }
  }
}
8 Answers

You could use a recursive function to collect all the values. Then use reduce to create a nested object from the values:

const initObject = { 
  value: 5,
  next: {
   value: 10,
   next: {
     value: 15,
     next: null
   }
  }
}

const getValues = ({ value, next }) =>
  next 
    ? [value, ...getValues(next)] 
    : [value]

const createObject = values => 
  values.reduce((next, value) => ({ value, next }), null)

const output = createObject(getValues(initObject))

console.log(output)

let newObject = null;

for(let o = initObject; o; o = o.next) {
    newObject = { value: o.value, next: newObject };
}

What this is doing is looping the initialObject from the outer layer inwards (using the next property to go from layer to layer until we reach null) while constructing the newObject from the inside outwards (each constructed layer will use the previous layer, stored as the current value of newObject, as the next property, hence the initial value of newObject is null), like so:

Note: As pointed out by @jperl in a comment bellow, if the objects have multiple properties (not just value), then simply use a spread syntax to include them all in newObject by replacing:

newObject = { value: o.value, next: newObject };

with:

newObject = { ...o, next: newObject };

Demo:

const initObject = { value: 5, next: { value: 10, next: { value: 15, next: null } } };

let newObject = null;

for(let o = initObject; o; o = o.next) {
    newObject = { value: o.value, next: newObject };
}

console.log(newObject);

Here's a function which does the job, the process is:

  • Build an array of the value values
  • Reverse the array (using Array.reverse)
  • Rebuild your object structure with the reversed array values
const reverseObject = (object) => {
  const values = [];
  let currentObject = object;
  while (currentObject && currentObject.value) {
    values.push(currentObject.value);
    currentObject = currentObject.next;
  }
  const reversedValues = values.reverse();
  const newObject = {};
  let currentNewObject = newObject;
  for (let i = 0; i < reversedValues.length; i++) {
    currentNewObject.value = reversedValues[i];
    currentNewObject.next = null;
    if (i < reversedValues.length - 1) {
      currentNewObject = currentNewObject.next = {};
    }
  }
  return newObject;
};

As Bergi already mentioned in the comments, this can be done using recursion. It is even very concise and readable if you do it as follows. It iterates through each (nested) node and builds up an inverted object using the nextAccumulator variable.

function invert({value, next}, nextAccumulator = null) {
    const node = {value, next: nextAccumulator};
    return next ? invert(next, node) : node;
}

const inverted = invert({
    value: 5,
    next: {
        value: 10,
        next: {
            value: 15,
            next: null,
        },
    },
});

console.log(inverted);

You could take a single function approach with a second paramter for collecting the objects.

const
    reverse = ({ value, next: sub }, next = null) => sub
        ? reverse(sub, { value, next })
        : { value, next },
    object = { value: 5, next: { value: 10, next: { value: 15, next: null } } },
    result = reverse(object);

console.log(result);

You can do that in following steps:

  • Create a function to get all the values in form of array in order
  • reverse the array
  • convert that array back to object using recursion

const newObject = {
  value: 15,
  next: {
    value: 10,
    next: {
      value: 5,
      next: null
    }
  }
}

function reverse(obj){
  let values = [];
  values.reverse();
  function getValue(tempObj){
    values.push(tempObj.value);
    if(tempObj.next){
      getValue(tempObj.next);
    }
  }
  getValue(obj)
  const ob = {};
  let  i = 0;
  function reassignValue(tempObj){
    if(i >= values.length){
      console.log(i)
      return;
    }
    tempObj.value = values[i];
    tempObj.next = {};
    i++;
    reassignValue(tempObj.next);
    
    
    
  }
  reassignValue(ob);
  return ob
}
console.log(reverse(newObject))

That's a linked list. You'll easily find a reverse LinkedList algorithm on the Internet.

Note that I don't need to convert anything.

Typescript

type LinkedList = {
  value: number,
  next: LinkedList
} | null

const list: LinkedList = {
  value: 5,
  next: {
    value: 10,
    next: {
      value: 15,
      next: null
    }
  },
}

const reverseLinkedList = (list: LinkedList) => {
  let prev = null;
  let current = list
  let next = null
  while (current != null) {
    next = current.next
    current.next = prev
    prev = current
    current = next
  }
  list = prev
  return list
}



console.log(reverseLinkedList(list))

Javascript

const list = {
  value: 5,
  next: {
    value: 10,
    next: {
      value: 15,
      next: null
    }
  },
}

const reverseLinkedList = (list) => {
  let prev = null;
  let current = list
  let next = null
  while (current != null) {
    next = current.next
    current.next = prev
    prev = current
    current = next
  }
  list = prev
  return list
}



console.log(reverseLinkedList(list))

You can use recursion:

let initObject={value:5,next:{value:10,next:{value:15,next:null}}};

let flip = (obj,nexts=[]) =>{
    nexts.push(obj.value);
    if (obj.next){
        flip(obj.next,nexts)
    }
    obj.value = nexts.shift()
    return obj;
}

let result = flip(initObject)
console.log(result);
let original = flip(result)
console.log(original)

Related