Найти все значения по определенному ключу в глубоко вложенном объекте |Javascript - PullRequest
0 голосов
/ 25 февраля 2019

Как найти все значения по определенному ключу в глубоко вложенном объекте?

Например, если у меня есть такой объект:

const myObj = {
  id: 1,
  children: [
    {
      id: 2,
      children: [
        {
          id: 3
        }
      ]
    },
    {
      id: 4,
      children: [
        {
          id: 5,
          children: [
            {
              id: 6,
              children: [
                {
                  id: 7,
                }
              ]
            }
          ]
        }
      ]
    },
  ]
}

Как бы получить массив всех значений во всех гнездах этого объекта по ключу id.

Примечание: children является непротиворечивым именем, и id не будет существовать вне объекта children.

Так что из obj я хотел бы создать массиввот так:

const idArray = [1, 2, 3, 4, 5, 6, 7]

Заранее спасибо!

Ответы [ 6 ]

0 голосов
/ 28 августа 2019

Это немного поздно, но для всех, кто найдет это, вот простая, универсальная рекурсивная функция:

function findAllByKey(obj, keyToFind) {
  return Object.entries(obj)
    .reduce((acc, [key, value]) => (key === keyToFind)
      ? acc.concat(value)
      : (typeof value === 'object')
      ? acc.concat(findAllByKey(value, keyToFind))
      : acc
    , [])
}

// USAGE
findAllByKey(myObj, 'id')
0 голосов
/ 25 февраля 2019

Примечание: children - это непротиворечивое имя, и id не будет существовать вне объекта children.

Так что из obj я хотел бы создать массивнапример:

const idArray = [1, 2, 3, 4, 5, 6, 7]

Учитывая, что вопрос не содержит каких-либо ограничений относительно того, как вывод получен из ввода, и что вход является согласованным, где значение свойства "id" являетсясвойство digit и id определяется только в свойстве "children", за исключением случая первого "id" в объекте, входной простой объект JavaScript может быть преобразован в строку JSON с использованием JSON.stringify(), RegExp/"id":\d+/g соответствует свойству "id" и одному или нескольким цифровым символам после имени свойства, которое затем сопоставляется с .match() цифрой в предыдущем совпадении с помощью Regexp \d+ и преобразует значение массива в JavaScriptчисло с использованием оператора сложения +

const myObject = {"id":1,"children":[{"id":2,"children":[{"id":3}]},{"id":4,"children":[{"id":5,"children":[{"id":6,"children":[{"id":7}]}]}]}]};

let res = JSON.stringify(myObject).match(/"id":\d+/g).map(m => +m.match(/\d+/));

console.log(res);

JSON.stringify() replacer В качестве альтернативы можно использовать .push() значение каждого "id" имени свойства в пределахобъект в массив

const myObject = {"id":1,"children":[{"id":2,"children":[{"id":3}]},{"id":4,"children":[{"id":5,"children":[{"id":6,"children":[{"id":7}]}]}]}]};

const getPropValues = (o, prop) => 
  (res => (JSON.stringify(o, (key, value) => 
    (key === prop && res.push(value), value)), res))([]);

let res = getPropValues(myObject, "id");

console.log(res);

Поскольку значения свойств входных данных для сопоставления являются цифрами, все объекты JavaScript можно преобразовать в строку и RegExp \D может использоваться для замены всех символов, которые не являются цифрами, распространения результирующей строки в массив и .map() цифр в числах JavaScript

let res = [...JSON.stringify(myObj).replace(/\D/g,"")].map(Number)
0 голосов
/ 25 февраля 2019

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

Используется Object.entries(), Object.keys(), Array.reduce(), Array.isArray(), Array.map() и Array.flat().

Условие остановки - когда объектпередано пусто:

const myObj = {
  id: 1,
  anyProp: [{
    id: 2,
    thing: { a: 1, id: 10 },
    children: [{ id: 3 }]
  }, {
    id: 4,
    children: [{
      id: 5,
      children: [{
        id: 6,
        children: [{ id: 7 }]
      }]
    }]
  }]
};

const getValues = prop => obj => {
  if (!Object.keys(obj).length) { return []; }

  return Object.entries(obj).reduce((acc, [key, val]) => {
    if (key === prop) {
      acc.push(val);
    } else {
      acc.push(Array.isArray(val) ? val.map(getIds).flat() : getIds(val));
    }
    return acc.flat();
  }, []);
}

const getIds = getValues('id');

console.log(getIds(myObj));
0 голосов
/ 25 февраля 2019

Вы можете сделать рекурсивную функцию с помощью Object.entries примерно так:

const myObj = {
  id: 1,
  children: [{
      id: 2,
      children: [{
        id: 3
      }]
    },
    {
      id: 4,
      children: [{
        id: 5,
        children: [{
          id: 6,
          children: [{
            id: 7,
          }]
        }]
      }]
    },
  ]
};

function findIds(obj) {
  const entries = Object.entries(obj);
  let result = entries.map(e => {
    if (e[0] == "children") {
      return e[1].map(child => findIds(child));
    } else {
      return e[1];
    }
  });
  function flatten(arr, flat = []) {
    for (let i = 0, length = arr.length; i < length; i++) {
      const value = arr[i];
      if (Array.isArray(value)) {
        flatten(value, flat);
      } else {
        flat.push(value);
      }
    }
    return flat;
  }
  return flatten(result);
}

var ids = findIds(myObj);
console.log(ids);

Функция выравнивания с этот ответ

Синтаксис ES5:

var myObj = {
  id: 1,
  children: [{
      id: 2,
      children: [{
        id: 3
      }]
    },
    {
      id: 4,
      children: [{
        id: 5,
        children: [{
          id: 6,
          children: [{
            id: 7,
          }]
        }]
      }]
    },
  ]
};

function findIds(obj) {
  const entries = Object.entries(obj);
  let result = entries.map(function(e) {
    if (e[0] == "children") {
      return e[1].map(function(child) {
        return findIds(child)
      });
    } else {
      return e[1];
    }
  });
  function flatten(arr, flat = []) {
    for (let i = 0, length = arr.length; i < length; i++) {
      const value = arr[i];
      if (Array.isArray(value)) {
        flatten(value, flat);
      } else {
        flat.push(value);
      }
    }
    return flat;
  }
  return flatten(result);
}

var ids = findIds(myObj);
console.log(ids);
0 голосов
/ 25 февраля 2019

Использование рекурсии.

const myObj = {  id: 1,  children: [    {      id: 2,      children: [        {          id: 3        }      ]    },    {      id: 4,      children: [        {          id: 5,          children: [            {              id: 6,              children: [                {                  id: 7,                }              ]            }          ]        }      ]    },  ]},
    loop = (array, key, obj) => {
      if (!obj.children) return;
      obj.children.forEach(c => {
        if (c[key]) array.push(c[key]); // is not present, skip!
        loop(array, key, c);
      });
    },
    arr = myObj["id"] ? [myObj["id"]] : [];
    
loop(arr, "id", myObj);
console.log(arr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 25 февраля 2019

Вы можете сделать рекурсивную функцию, подобную этой:

idArray = []

function func(obj) {
  idArray.push(obj.id)
  if (!obj.children) {
    return
  }

  obj.children.forEach(child => func(child))
}

Фрагмент для вашего образца:

const myObj = {
  id: 1,
  children: [{
      id: 2,
      children: [{
        id: 3
      }]
    },
    {
      id: 4,
      children: [{
        id: 5,
        children: [{
          id: 6,
          children: [{
            id: 7,
          }]
        }]
      }]
    },
  ]
}

idArray = []

function func(obj) {
  idArray.push(obj.id)
  if (!obj.children) {
    return
  }

  obj.children.forEach(child => func(child))
}

func(myObj)
console.log(idArray)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...