Итерация по дереву JSON для рекурсивного извлечения Parent и Child - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть файл JSON, из которого я получаю все ключи.Мне нужно получить ключи от родителей к ребенку.Например:

Родитель---- Child1---- Child2---- Child3-------- Child31-------- Child32---- Child4

Может ли это быть достигнуто путем рекурсии?Для перебора файла я использую следующий код:

function runRecurse(objLevel) {
   for (var innerKey in objLevel) {
      if (objLevel[innerKey] !== null){
         console.log(innerKey);
         runRecurse(objLevel[innerKey]);    
      }
   }                     
}

Есть ли способ получить результат, как в определенном формате:

NoParent - ParentРодитель - Ребенок1Родитель - Ребенок2Родитель - Child3Child3 - Child31Child3 - Child32Родитель - Child4

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Чтобы получить все ключи в виде отдельных путей, вы можете взять записи объекта и выполнить итерацию, проверив, являются ли значения также объектами, а затем выбрать дополнительные ключи или только фактический ключ для результата.

function getKeys(object) {
    return Object
        .entries(object)
        .reduce((r, [k, v]) =>
            r.concat(v && typeof v === 'object'
                ? getKeys(v).map(sub => [k].concat(sub))
                : k
            ),
            []
        );
}

var data = { v1: { Cr: { getrt: { input: { R: { Cd: "nt", Ud: "ing", Pd: "g", Mr: "ng", Se: "ng", Pe: "ing", Psion: "g", Rt: "L", Cd2: "xsring", Cag: "xsngth", NnfigID: "xsng", CryFlag1: "xength", C2: "xength", Custo3: "xength", Cus4: "xngth", tars: "ns", taace: "h.0" }, Reqails: { Amber: "xsd:string", B: "x", KenMI: "xg", targas: "ns", targace: "h" }, Inqutails: { "Inqnt[]": { Ar: "x", B: "x", KI: "x", ts: "ns", tce: "h0" }, tas: "ns", tace: "h" }, Reqdy: { Ise: "Inq", Tnt: "x", Ald: "x", Fme: "x", Fmjke: "xtern", Mme: "xttern", Lame: "xs", Fals: { "Ado[]": { Addme: "x", Adde: "AdnalNam", taas: "", taace: "ht" }, Noents: "x", talias: "n", tapace: "h" }, Ad1: "xh", A2: "x", Ae1: "xs", St: "x", L1: "xs", L2: "xs", Cy: "x", Ste: "S", Pal: "x", Is: { "I[]": { Aine: "x", Set: "xth", L1: "x", L2: "x", C: "x", Se: "St", Pal: "n", Ape: "", tas: "ns", tpace: "" } } } } } } } },
    result = getKeys(data);

console.log(result.map(a => a.join(' ')));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Последний родительский и последний узел:

function getKeys(object, parent = 'noParent') {
    return object && typeof object === 'object'
        ? Object
            .entries(object)
            .reduce((r, [k, v]) => [...r, [parent, k], ...getKeys(v, k)], [])
        : [];
}

var data = { v1: { Cr: { getrt: { input: { R: { Cd: "nt", Ud: "ing", Pd: "g", Mr: "ng", Se: "ng", Pe: "ing", Psion: "g", Rt: "L", Cd2: "xsring", Cag: "xsngth", NnfigID: "xsng", CryFlag1: "xength", C2: "xength", Custo3: "xength", Cus4: "xngth", tars: "ns", taace: "h.0" }, Reqails: { Amber: "xsd:string", B: "x", KenMI: "xg", targas: "ns", targace: "h" }, Inqutails: { "Inqnt[]": { Ar: "x", B: "x", KI: "x", ts: "ns", tce: "h0" }, tas: "ns", tace: "h" }, Reqdy: { Ise: "Inq", Tnt: "x", Ald: "x", Fme: "x", Fmjke: "xtern", Mme: "xttern", Lame: "xs", Fals: { "Ado[]": { Addme: "x", Adde: "AdnalNam", taas: "", taace: "ht" }, Noents: "x", talias: "n", tapace: "h" }, Ad1: "xh", A2: "x", Ae1: "xs", St: "x", L1: "xs", L2: "xs", Cy: "x", Ste: "S", Pal: "x", Is: { "I[]": { Aine: "x", Set: "xth", L1: "x", L2: "x", C: "x", Se: "St", Pal: "n", Ape: "", tas: "ns", tpace: "" } } } } } } } },
    result = getKeys(data);

console.log(result.map(a => a.join(' ')));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 27 ноября 2018

Предполагая, что ваши данные имеют следующую форму:

const data = {
  'parent': {
    'child1': 1,
    'child2': 2,
    'child3': {
      'child31': 31,
      'child32': 32
    },
    'child4': 4
  }
}

У вас есть правильное представление о рекурсии, но для рекурсии необходимы два элемента:

  1. Естьбазовый случай для завершения,
  2. рекурсивный (с надеждой уменьшенным) значением.

В этом случае базовый случай (1.) не имеет дочерних элементов, поэтому мы пишемэта функция, которая будет возвращать true, если элемент не имеет дочерних элементов.Вам, вероятно, придется изменить его для массивов.

function isEmpty(obj) {
  let numProperties = 0;
  for (let property in obj) {
    if (obj.hasOwnProperty(property)) {
      ++numProperties;
    }
  }
  return numProperties === 0;
}

С базовым регистром и некоторыми данными, давайте вернемся к нему.Вы хотите применить функцию к каждому родительскому элементу (ключу) и его дочернему элементу (элементу), а затем вызвать ее для каждого дочернего элемента (2.), поэтому мы напишем функцию отображения для неупорядоченных деревьев:

function mapParentChildPairs(f, obj) {
  // If this element has no children, we have reached the end, so stop
  if (isEmpty(obj)) {
    return;
  } else {
    // Otherwise, get each key in the object
    for (let item in obj) {
      if (obj.hasOwnProperty(item)) {
        // Apply the function to the key and its value
        f(item, obj[item]);
        // And recurse over the item at that key, which may be more objects
        // or simply an atomic value that will end the recursion.
        mapParentChildPairs(f, obj[item]);
      }
    }
  }
}

Ваш пример использовал console.log, поэтому давайте передадим это как функцию:

mapParentChildPairs(console.log, data);
...