Как показать подкатегорию категории на основе массива - PullRequest
0 голосов
/ 28 мая 2019

У меня есть массив, состоящий из некоторых данных для отображения категории и подкатегорий.

{id: "5", parent_id: "0", lable: "Movie"}
{id: "20", parent_id: "5", lable: "Action"}
{id: "15", parent_id: "43", lable: "J.K Rowling"}
{id: "43", parent_id: "0", lable: "Book"}
{id: "20", parent_id: "2", lable: "James Bond Series"}
{id: "3", parent_id: "0", lable: "Music"}
{id: "39", parent_id: "15", lable: "Harry Potter Series"}

Я хочу отсортировать и показать эти данные примерно так:

> Movie
>> Action  
>>>James Bond Series

>Book
>>J.K Rowling
>>>Harry Potter Series

Ответы [ 5 ]

2 голосов
/ 28 мая 2019

Это может быть достигнуто с помощью рекурсивного метода.

const arr = [{id: "5", parent_id: "0", lable: "Movie"},
{id: "20", parent_id: "5", lable: "Action"},
{id: "15", parent_id: "43", lable: "J.K Rowling"},
{id: "43", parent_id: "0", lable: "Book"},
{id: "20", parent_id: "2", lable: "James Bond Series"},
{id: "3", parent_id: "0", lable: "Music"},
{id: "39", parent_id: "15", lable: "Harry Potter Series"}];

const render = (arr, id) => {
  const div = document.createElement('div');
  const span = document.createElement('span');
  span.innerText = arr.find(e => e.id === id).lable;
  div.appendChild(span);
  arr.filter(e => e.parent_id === id).forEach(sub => {
    div.appendChild(render(arr, sub.id));
  });
  return div;
}

arr.filter(e => e.parent_id === "0").forEach(main =>    document.querySelector('div').appendChild(render(arr, main.id)));
div {
  margin-left: 5px;
}
<div></div>
2 голосов
/ 28 мая 2019

Для общего решения вы можете взять свои данные и реализовать класс легкого дерева, в котором у каждого узла есть значение и список дочерних узлов этого узла. Затем вы можете создать итератор или аналогичную функцию, которая будет выполнять обход дерева в глубину. Он может возвращать информацию о глубине, которая позволит вам печатать значения с правильным отступом.

let data = [{id: "5", parent_id: "0", lable: "Movie"},{id: "20", parent_id: "5", lable: "Action"},{id: "15", parent_id: "43", lable: "J.K Rowling"},{id: "43", parent_id: "0", lable: "Book"},{id: "2", parent_id: "20", lable: "James Bond Series"},{id: "3", parent_id: "0", lable: "Music"},{id: "39", parent_id: "15", lable: "Harry Potter Series"}]


class Node {
  constructor(id, value) {
      this.id = id
      this.value = value
      this.children = []
    }
    * getTree(depth = 0) {  // an iterator that yields itself and chidlren
      yield [this.value, depth]
      for (let child of this.children) {
        yield* child.getTree(depth + 1)
      }
    }
}

// Create the nodes using a helper object to keep track of IDs
// Make sure the parent exists (even without info) before trying to push children

let tree = data.reduce((tree, {id,parent_id, lable}) => {
  if (tree[id] === undefined) tree[id] = new Node(id, lable)
  else Object.assign(tree[id], {id,value: lable})

  if (tree[parent_id] == undefined) tree[parent_id] = new Node()

  tree[parent_id].children.push(tree[id])
  return tree
}, { 0: new Node(0, "root")})

// Root of the tree is at id 0
let root = tree[0]

// now iterate of the children using the depth for layout
for (let [node, depth] of root.getTree()) {
  console.log('>'.repeat(depth), node)
}

// Show only movies by starting at a different node:
console.log("----------- movies -------------")
let start = tree[5]
for (let [node, depth] of start.getTree()) {
  console.log('>'.repeat(depth), node)
}
2 голосов
/ 28 мая 2019

Вам нужно древовидное представление ваших данных, так как ваши данные являются таблицей самоссылки. Итак, вам нужно написать код, который переведет вашу плоскую структуру в дерево. Например, вы можете использовать следующий код для этого:

const makeTree = (array, id, parentId, parentValue) =>
  array
    .filter(node => {
      return node[parentId] === parentValue;
    })
    .map(node => {
      node["items"] = makeTree(array, id, parentId, node[id]);
      return node;
    });

Где array - ваш исходный массив, id - имя поля идентификатора, parentId - имя поля, содержащего родительский идентификатор, parentValue - идентификатор корневого узла.

Вы можете вызвать эту функцию следующим образом, чтобы создать дерево из вашего массива:

const tree = makeTree(array, "id", "parent_id", "0");

Где array - ваш исходный массив:

const array = [
  { id: "5", parent_id: "0", lable: "Movie" },
  { id: "20", parent_id: "5", lable: "Action" },
  { id: "15", parent_id: "43", lable: "J.K Rowling" },
  { id: "43", parent_id: "0", lable: "Book" },
  { id: "2", parent_id: "20", lable: "James Bond Series" },
  { id: "3", parent_id: "0", lable: "Music" },
  { id: "39", parent_id: "15", lable: "Harry Potter Series" }
];

Результирующие элементы массива будут содержать поле items, которое является массивом дочерних узлов.

После этого вы можете создать рекурсивную функцию, которая будет визуализировать это дерево с помощью jQuery. Например:

const renderLevel = items => {
  return $("<ul>").append(
    items.map(item =>
      $("<li>")
        .html(item.lable)
        .append(renderLevel(item.items))
    )
  );
};

Вызовите его и передайте в него переменную tree:

$(() => {
  $("body").append(renderLevel(tree));
});

Это образец .

const array = [
  { id: "5", parent_id: "0", lable: "Movie" },
  { id: "20", parent_id: "5", lable: "Action" },
  { id: "15", parent_id: "43", lable: "J.K Rowling" },
  { id: "43", parent_id: "0", lable: "Book" },
  { id: "2", parent_id: "20", lable: "James Bond Series" },
  { id: "3", parent_id: "0", lable: "Music" },
  { id: "39", parent_id: "15", lable: "Harry Potter Series" }
];

const makeTree = (array, id, parentId, parentValue) =>
  array
    .filter(node => {
      return node[parentId] === parentValue;
    })
    .map(node => {
      node["items"] = makeTree(array, id, parentId, node[id]);
      return node;
    });

const tree = makeTree(array, "id", "parent_id", "0");
console.log(JSON.stringify(tree))

const renderLevel = items => {
  return $("<ul>").append(
    items.map(item =>
      $("<li>")
        .html(item.lable)
        .append(renderLevel(item.items))
    )
  );
};

$(() => {
  $("body").append(renderLevel(tree));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
1 голос
/ 28 мая 2019

Получите сначала дерево, а затем плоское представление.

function getTree(array, root) {
    var o = {};
    array.forEach(payload => {
        Object.assign(o[payload.id] = o[payload.id] || {}, { payload });
        o[payload.parent_id] = o[payload.parent_id] || {};
        o[payload.parent_id].children = o[payload.parent_id].children || [];
        o[payload.parent_id].children.push(o[payload.id]);
    });
    return o[root].children;
}

function getFlat(array = []) {
    return array.reduce((r, { payload, children }) =>
        r.concat(payload, getFlat(children)), []);
}

var data = [{ id: "5", parent_id: "0", lable: "Movie" }, { id: "20", parent_id: "5", lable: "Action" }, { id: "15", parent_id: "43", lable: "J.K Rowling" }, { id: "43", parent_id: "0", lable: "Book" }, { id: "2", parent_id: "20", lable: "James Bond Series" }, { id: "3", parent_id: "0", lable: "Music" }, { id: "39", parent_id: "15", lable: "Harry Potter Series" }],
    result = getFlat(getTree(data, '0'));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 28 мая 2019

Просто используйте функцию фильтра, как показано ниже для каждой категории и подкатегории:

var arr = [{id: "5", parent_id: "0", lable: "Movie"},
{id: "20", parent_id: "5", lable: "Action"},
{id: "15", parent_id: "43", lable: "J.K Rowling"},
{id: "43", parent_id: "0", lable: "Book"},
{id: "20", parent_id: "2", lable: "James Bond Series"},
{id: "3", parent_id: "0", lable: "Music"},
{id: "39", parent_id: "15", lable: "Harry Potter Series"}];

function isParent(element, index, array) {
  return (element.parent_id == "0");
}

let filtered = arr.filter(isParent);

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