Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

97
Vistas
Iterative depth-first traversal with remembering value's paths

I need help with specific implementation of iterative depth first traversal algorithm. I have an object like this (it's just an example, object might have more properties and be deeper nested):

const root = {
  a: 1,
  b: {
    c: {
      d: {
        e: 2,
        f: 3,
      }
    },
    g: [
      {
        h: 4,
        i: 5,
      },
      {
        j: 6,
        k: 7,
      }
    ]
  }
}

What I need is a function that would traverse the whole object and return an array like this:

[
  {"a": 1},
  {"b.c.d.e": 2},
  {"b.c.d.f": 3},
  {"b.g.0.h": 4},
  {"b.g.0.i": 5},
  {"b.g.1.j": 6},
  {"b.g.1.k": 7},
]

I managed to create an algorithm that sort of solves my problem, but needs one additional step in the end. Result of the algorithm is an array of strings like that:

[
  'a^1',
  'b.c.d.e^2',
  'b.c.d.f^3',
  'b.g.0.h^4',
  'b.g.0.i^5',
  'b.g.1.j^6',
  'b.g.1.k^7'
]

so in order to achieve what I want I have to do one full iteration over the result of my algorithm, split strings by ^ symbol and then create objects based on that.

This is the part that I need help with - how can I improve/change my solution so I don't need to do that last step?

function dft(root) {
  let stack = [];
  let result = [];
  const isObject = value => typeof value === "object";
  stack.push(root);
  while (stack.length > 0) {
    let node = stack.pop();
    if (isObject(node)) {
      Object.entries(node).forEach(([childNodeKey, childNodeValue]) => {
        if (isObject(childNodeValue)) {
          const newObject = Object.fromEntries(
            Object.entries(childNodeValue).map(([cnk, cnv]) => {
              return [`${childNodeKey}.${cnk}`, cnv];
            })
          );
          stack.push(newObject);
        } else {
          stack.push(`${childNodeKey}^${childNodeValue}`);
        }
      })
    } else {
      result.push(node);
    }
  }
  return result.reverse();
}
about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

You can push the childNodeKey childNodeValue pair directly as an object to your result array.

Change

stack.push(`${childNodeKey}^${childNodeValue}`);

to

const newEntry = {}
newEntry[childNodeKey] = childNodeValue
result.push(newEntry);

or with ES2015 syntax (you would need a transpiler for browser compatibility)

result.push({[childNodeKey]: childNodeValue});

Complete function:

const root = {
  a: 1,
  b: {
    c: {
      d: {
        e: 2,
        f: 3,
      }
    },
    g: [
      {
        h: 4,
        i: 5,
      },
      {
        j: 6,
        k: 7,
      }
    ]
  }
}

function dft(root) {
  let stack = [];
  let result = [];
  const isObject = value => typeof value === "object";
  stack.push(root);
  while (stack.length > 0) {
    let node = stack.pop();
    if (isObject(node)) {
      Object.entries(node).forEach(([childNodeKey, childNodeValue]) => {
        if (isObject(childNodeValue)) {
          const newObject = Object.fromEntries(
            Object.entries(childNodeValue).map(([cnk, cnv]) => {
              return [`${childNodeKey}.${cnk}`, cnv];
            })
          );
          stack.unshift(newObject);
        } else {
          const newEntry = {}
          newEntry[childNodeKey] = childNodeValue
          result.push({[childNodeKey]: childNodeValue});
        }
      })
    } else {
      result.push(node);
    }
  }
  return result;
}

console.log(dft(root))

about 4 years ago · Juan Pablo Isaza Denunciar

0

I'd keep pairs <keys,value> in the stack and only create a string key when storing a newly created object:

function dft(obj) {
    let stack = []
    let res = []

    stack.push([[], obj])

    while (stack.length) {
        let [keys, val] = stack.pop()

        if (!val || typeof val !== 'object') {
            res.push({
                [keys.join('.')]: val
            })
        } else {
            Object.entries(val).forEach(p => stack.push([
                keys.concat(p[0]),
                p[1],
            ]))
        }
    }

    return res.reverse()
}

//

const root = {
  a: 1,
  b: {
    c: {
      d: {
        e: 2,
        f: 3,
      }
    },
    g: [
      {
        h: 4,
        i: 5,
      },
      {
        j: 6,
        k: 7,
      }
    ]
  }
}

console.log(dft(root))

about 4 years ago · Juan Pablo Isaza Denunciar

0

As you mentioned, you almost got it complete. Just make the array entry an object just before pushing it into result. By splitting Array.prototype.split('^') you can get 'b.g.0.h^4' >>> ['b.g.0.h', '4']. So, rest is a cake:

if (isObject(node)) {
 ...
} else {
  const keyAndValue = node.split('^')
  // approach 1)
  // const key = keyAndValue[0]
  // const value = keyAndValue[1]
  // dynamic key setting
  // result.push({[key]: value});

  // approach 2)
  // or in short,
  // dynamic key setting
  result.push({[keyAndValue[0]]: keyAndValue[1]});
}
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda