У меня есть куча объектов в плоской структуре. Эти объекты имеют ID
и в ParentID
собственность , чтобы они могли быть расположены на деревьях. Они не в определенном порядке. Каждое ParentID
свойство не обязательно совпадает с ID
в структуре. Поэтому их может быть несколько деревьев, выходящих из этих объектов.
Как бы вы обработали эти объекты для создания результирующих деревьев?
Я не так далек от решения, но уверен, что оно далеко от оптимального ...
Мне нужно создать эти деревья, чтобы затем вставить данные в базу данных в правильном порядке.
Там нет циркулярных ссылок. Узел является RootNode, когда ParentID == null или когда ParentID не может быть найден в других объектах
Ответы:
Сохраните идентификаторы объектов в хэш-таблице, сопоставленной с конкретным объектом. Перечислите все объекты и найдите их родителей, если они существуют, и соответственно обновите указатель их родителей.
источник
Основываясь на ответе Мехрдада Афшари и комментариях Эндрю Хэнлона для ускорения, вот мое мнение.
Важное отличие от исходной задачи: корневой узел имеет идентификатор == parentID.
источник
Вот простой алгоритм JavaScript для разбора плоской таблицы на структуру родительского / дочернего дерева, которая выполняется за N раз:
источник
console.log(JSON.stringify(root, null, 2));
чтобы красиво распечатать результат.Решение Python
Например:
Производит:
источник
def recurse(id, pages): for row in rows: if row['id'] == id: print(f'''{row['id']}:{row['parent_id']} {row['path']} {row['title']}''') recurse(row['id'], rows)
Версия JS, которая возвращает один корень или массив корней, каждый из которых будет иметь свойство массива Children, содержащее связанные дочерние элементы. Не зависит от упорядоченного ввода, прилично компактен и не использует рекурсию. Наслаждайтесь!
источник
Нашел отличную версию JavaScript здесь: http://oskarhane.com/create-a-nested-array-recursively-in-javascript/
Допустим, у вас есть такой массив:
И вы хотите, чтобы объекты были вложены так:
Вот рекурсивная функция, которая делает это возможным.
Usuage:
источник
Для всех, кто интересуется версией решения Юджина на C #, обратите внимание, что node_list доступен как карта, поэтому используйте вместо него словарь.
Имейте в виду, что это решение работает, только если таблица отсортирована по parent_id .
Узел определяется следующим образом.
источник
new Node { parent_id = 7, id = 9 },
неnode_list.Add(item.id, item);
может быть завершен, потому что ключ не может повторяться; это опечатка; поэтому вместо id = 9 введите id = 8Я написал общее решение на C #, основанное на ответе @Mehrdad Afshari:
источник
Вот Java-решение ответа Мехрдада Афшари.
источник
Мне кажется, что вопрос неопределенный, я бы, вероятно, создал карту из идентификатора фактического объекта. В псевдо-Java (я не проверял, работает ли он / компилируется), это может быть что-то вроде:
И посмотреть каждого родителя:
Повторно используя
getRealObject(ID)
и делая карту из объекта в коллекцию объектов (или их идентификаторов), вы также получаете карту parent-> children.источник
Я могу сделать это за 4 строки кода и за O (n log n), предполагая, что Dictionary - это что-то вроде TreeMap.
РЕДАКТИРОВАТЬ : Хорошо, и теперь я прочитал, что некоторые родительские идентификаторы являются поддельными, так что забудьте об этом и сделайте следующее:
источник
Большинство ответов предполагают, что вы хотите сделать это за пределами базы данных. Если ваши деревья относительно статичны по своей природе и вам просто нужно каким-то образом отобразить деревья в базу данных, вы можете рассмотреть возможность использования представлений вложенных множеств на стороне базы данных. Проверьте книги Джо Селко (или здесь для обзора Селко). При любом подходе вы можете полностью пропустить отображение деревьев, прежде чем загружать данные в базу данных. Просто подумал, что я предложу это в качестве альтернативы, это может быть совершенно не подходит для ваших конкретных потребностей. Вся часть «правильного порядка» исходного вопроса в некоторой степени подразумевает, что вам нужен порядок, чтобы быть «правильным» в БД по какой-то причине? Это может подтолкнуть меня к обработке деревьев там же.
Если вы все равно привязаны к Oracle dbs, проверьте их CONNECT BY на подходы прямого SQL.
источник
Это не совсем то, что искал аскер, но мне было трудно обернуть голову вокруг неоднозначно сформулированных ответов, представленных здесь, и я все еще думаю, что этот ответ подходит под заголовком.
Мой ответ - для отображения плоской структуры в дереве непосредственно на объекте, где все, что у вас есть, -
ParentID
на каждом объекте.ParentID
естьnull
или0
если это корень. Напротив спрашивающего, я предполагаю, что все действительныеParentID
указывают на что-то еще в списке:источник
вот реализация ruby:
Он будет каталогизирован по имени атрибута или результату вызова метода.
источник
Принятый ответ выглядит слишком сложным для меня, поэтому я добавляю его версии для Ruby и NodeJS
Предположим, что список плоских узлов имеет следующую структуру:
Функции, которые превратят структуру плоского списка выше в дерево, выглядят следующим образом
для Ruby:
для NodeJS:
источник
null
должна бытьundefined
null == undefined => true
в NodeJSодин из элегантных способов сделать это - представить элементы в списке в виде строки, содержащей список родителей, разделенных точками, и, наконец, значение:
При сборке дерева вы получите что-то вроде:
У меня есть библиотека конфигурации, которая реализует эту конфигурацию переопределения (дерево) из аргументов командной строки (список). Алгоритм добавления одного элемента в список в дереве находится здесь .
источник
Вы застряли, используя только эти атрибуты? Если нет, то было бы неплохо создать массив дочерних узлов, где вы можете циклически пройти через все эти объекты один раз, чтобы создать такие атрибуты. Оттуда выберите узел с детьми, но без родителей и итеративно постройте свое дерево сверху вниз.
источник
Java-версия
источник