Генерировать плоский массив идентификаторов из многоуровневого дерева, используя функцию Reduce с рекурсией? - PullRequest
1 голос
/ 08 марта 2019

Я пытаюсь реализовать пользовательскую иерархию с использованием библиотеки js orgChart . методом getHierarchy() в библиотеке выводится объект, подобный следующему.

var datascource = {
            "id": "1",
            "children": [{
                "id": "2"
            }, {
                "id": "3",
                "children": [{
                    "id": "4"
                }, {
                    "id": "5",
                    "children": [{
                        "id": "6"
                    }, {
                        "id": "7"
                    }]
                }]
            }, {
                "id": "10"
            }, {
                "id": "12"
            }]
        };

Я хочу создать плоский массив из идентификаторов в дереве. например: //["1", "2", "3", "4", "5", "6", "7", "10", "12"]

Я придумал,

function getNestedArraysOfIds(node) {
    if (node.children == undefined) {
        return [node.id];
    } else {
        return [node.id,...node.children.map(subnode => (subnode.children==undefined) ? subnode.id: getNestedArraysOfIds(subnode))];
    }
}

function getIds(array) {
        return array.reduce((acc, subArray) =>
            (Array.isArray(subArray)) ? [...acc, ...getIds(subArray)] : [...acc, subArray]);
    }

var idArrays = getNestedArraysOfIds(datascource );
var ids = getIds(idArrays); //["1", "2", "3", "4", "5", "6", "7", "10", "12"]

Я попытался сделать это с помощью одной функции сокращения, но в итоге я написал две функции, обе из которых являются рекурсивными. Существует ли много элегантных и эффективных способов сделать это с помощью единой функции уменьшения?

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

Ответы [ 3 ]

1 голос
/ 08 марта 2019

Вы можете выровнять детей, взяв отображение с concat.

function getFlat({ id, children = [] }) {
    return [id].concat(...children.map(getFlat));
}

var data = { id: "1", children: [{ id: "2" }, { id: "3", children: [{ id: "4" }, { id: "5", children: [{ id: "6" }, { id: "7" }] }] }, { id: "10" }, { id: "12" }] };

console.log(getFlat(data));

То же самое с функцией уменьшения

function getFlat({ id, children = [] }) {
    return children.reduce((r, o) => [...r, ...getFlat(o)], [id]);
}

var data = { id: "1", children: [{ id: "2" }, { id: "3", children: [{ id: "4" }, { id: "5", children: [{ id: "6" }, { id: "7" }] }] }, { id: "10" }, { id: "12" }] };

console.log(getFlat(data));
1 голос
/ 08 марта 2019

Используйте рекурсию с Array.flatMap() и распространите, чтобы получить идентификаторы и идентификаторы детей, и сведите в один массив:

const getIds = ({ id, children }) => children ? [id, ...children.flatMap(getIds)] : id;

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

const result = getIds(dataSource);

console.log(result);
0 голосов
/ 08 марта 2019

Вы можете создать простую функцию recursive и использовать for..in для ее итерации. Если ключ равен id, поместите его значение в массив, иначе, если значение ключа является массивом, например, значение ключа children является массивом, затем вызовите ту же рекурсивную функцию внутри для цикл и передать каждый объект

let datascource = {
  "id": "1",
  "children": [{
    "id": "2"
  }, {
    "id": "3",
    "children": [{
      "id": "4"
    }, {
      "id": "5",
      "children": [{
        "id": "6"
      }, {
        "id": "7"
      }]
    }]
  }, {
    "id": "10"
  }, {
    "id": "12"
  }]
};

let data = [];

function flatData(obj) {
  for (let keys in obj) {
    if (keys === 'id') {
      data.push(obj[keys])
    } else if (Array.isArray(obj[keys])) {
      obj[keys].forEach((item) => {
        flatData(item)
      })

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