Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 13, 2014 19:29:40

Rokot
Зарегистрирован: 2014-11-13
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Организация дерева элементов

Здравствуйте.

В изучении языка делаю первые шаги и для закрепления прочитанного стараюсь теорию совмещать с практикой, потому поставил себе задачу написать что-то вроде простого географического справочника с рядом функций. К сожалению, недостаток знаний порой препятствует реализации какой-либо идеи, а найти решение проблемы в пособиях или вопросах других пользователей удаётся не всегда, что вынуждает озадачить сообщество своим вопросом.

Подскажите, пожалуйста, как лучше решить следующую задачу:

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

- Европа
- - Беларусь
- - - Витебск
- - Россия
- - - Центральный федеральный округ
- - - - Москва
- - - - Московская область
- - - Южный федеральный округ
- - Украина
- Азия
- Африка

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

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

Спасибо.

Отредактировано Rokot (Ноя. 13, 2014 21:10:36)

Офлайн

#2 Ноя. 13, 2014 21:11:48

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2842
Репутация: +  186  -
Профиль   Отправить e-mail  

Организация дерева элементов

http://www.opennet.ru/docs/RUS/hierarchical_data/



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Ноя. 14, 2014 19:59:46

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Организация дерева элементов

На первых порах вполне подойдет система вложенных списков питона и cPickle для сериализации. Если возникнет проблема с объемом данных надежностью хранения или потребуется коллективный доступ с модификацией то тогда можно уже и в базах данных искать? Причем есть специальные базы для таких задачек. http://en.wikipedia.org/wiki/Graph_database
В учебных целях вы легко можете имитировать свою б.д. файловой системой.



Офлайн

#4 Ноя. 14, 2014 22:10:48

Rokot
Зарегистрирован: 2014-11-13
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Организация дерева элементов

doza_and
Благодарю за наводку. При написании этой программы преследую не столько исключительно учебные цели, сколько практические - она мне необходима в качестве песочницы, в которой можно разобраться и поэкспериментировать с методами/решениями, которые пригодятся в будущем.

Использовать текстовые файлы (если верно понял Ваши слова про БД системы) не хотелось бы по нескольким причинам: проблемы при изменении структуры записи, невозможность просмотреть все данные сразу, множество мелких файлов вместо одного у SQLite. В своё время, когда довелось немного кодить на PHP + MySQL, в процессе допиливания CMS, работающей на простых файлах, столкнулся со множеством проблем, которых при использовании MySQL или txtSQL не возникало.

P. S. Немного не по теме, но скажу о мотивации. Основной причиной начала изучения Питона была личная заинтересованность в описанной программе. Пролистав несколько страниц поисковой выдачи и покопавшись на нескольких десятках сайтов, нужного мне решения не нашёл. Из нескольких сравниваемых языков выбрал Питон за возможность создания кроссплатформенных приложений и положительные отзывы относительно формирования грамотного стиля написания. Именно поэтому хочу с самого начала сделать качественно и правильно, дабы готовое приложение можно было использовать сразу, постепенно дорабатывая его и дополняя необходимыми функциями.

Офлайн

#5 Ноя. 15, 2014 08:21:13

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

Организация дерева элементов

Rokot
Именно поэтому хочу с самого начала сделать качественно и правильно
Неа. Не получиться На то оно и начало…

Офлайн

#6 Ноя. 15, 2014 09:14:24

bismigalis
Зарегистрирован: 2010-10-02
Сообщения: 449
Репутация: +  47  -
Профиль   Отправить e-mail  

Организация дерева элементов

для такой задачи достаточно таблицы с полями id, parent_id, name
выгребаешь одним запросом все данные, потом в питоне строишь дерево

по научному это называется Adjacency List

Офлайн

#7 Ноя. 15, 2014 09:20:48

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Организация дерева элементов

Вы неправильно меня поняли.

Rokot
Использовать текстовые файлы
Посмотрите что я написал. У меня не было слов про текстовый файл. Pickle/cPickle позволяет сохранять объекты питона как в текстовом так и в двоичном виде.
Rokot
при изменении структуры записи
В деревьях нет понятия записи. Поэтому ваш довод непонятен. Вы имеете ввиду листья?
Rokot
невозможность просмотреть все данные сразу
Непонятно как вы их вообще хотите смотреть, каким инструментарием, в каком оформлении? Методы просмотра очень слабо связаны со способом хранения данных на диске (по крайней мере для малых объемов данных). Например сделайте dump в yaml файл и смотрите в текстовом редакторе. Чем вас это не устраивает? Это как раз в РСУБД нельзя посмотреть все данные сразу (и лучше такое требование вообще не ставить).
Rokot
множество мелких файлов
Файл можно сделать один файл. Почему вы взяли что их будет много? Если делать имитацию в файловой системе то да будет туча. Не нравится не делайте так.

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

В 90 процентов случаев достаточно загрузить все данные в память поработать а потом все выгрузить. В вашей постановке нет никаких предпосылок к применению другого подхода.
:)
a.yaml:
- Европа
  - Беларусь
    - Витебск
  - Россия
    - Центральный федеральный округ
      - Москва
      - Московская область
    - Южный федеральный округ
  - Украина
- Азия
- Африка
import yaml
a=yaml.load(open("a.yaml","r"))
Мне просто кажется вы бъетесь над этими двумя строчками.
Приведите возражения против такого подхода, тогда можно будет дальше обсуждать другие подходы.



Отредактировано doza_and (Ноя. 15, 2014 09:46:04)

Офлайн

#8 Ноя. 15, 2014 18:48:54

Rokot
Зарегистрирован: 2014-11-13
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Организация дерева элементов

4kpt_II
На то оно и начало…
Ну хоть основа будет, которую дальше можно допилить.


bismigalis, doza_and
Не исключаю, что на ход моих рассуждений невольно влияет опыт работы с PHP + MySQL, что и заводит в тупик. Постараюсь объяснить то, что имел в виду.

Допустим, у меня есть БД на SQLite, в которой есть таблица с полями id, name, level, parent, child, date и тому подобными. В этой таблице друг за другом следуют записи, подчинённость и вложения которых определяются значениями в полях level, parent, children.

Чтобы отобразить список сгруппированных элементов мне необходимо запросить в базе все элементы с level=1, потом для каждого из них в цикле (от 1 до n, где n - общее количество элементов с level=1) сделать запрос элементов с level=2 & parent=x, где x - родительский элемент. Либо вместо поиска по parent сразу использовать child, но, опять же, в цикле. Приблизительно так, строка за строкой, уровень за уровнем, реализовал бы это на PHP. Да, это ресурсозатратно и неприлично, потому и хочу найти правильный метод.

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


doza_and
У меня не было слов про текстовый файл.
Прошу извинить, если действительно не понял отсылку к cPickle. Вкупе со словами об имитации своей БД воспринял её в качестве предложения использовать данную функцию в качестве инструмента для записи данных в виде отдельных файлов. Виноват.


doza_and
Вы имеете ввиду листья?
Не совсем. Деревом данные будут после их вызова из БД, обработки и отрисовки. Имея одну БД со всеми данными могут без особых хлопот добавить в существующую таблицу новый столбец или переименовать существующие. Если же каждая запись будет представлена в виде отдельного файла a-la xml, то просто так все изменить не выйдет.


doza_and
Непонятно как вы их вообще хотите смотреть, каким инструментарием, в каком оформлении?
В данном случае подразумевал процесс просмотра данных человеком во время разработки. Для SQLite есть неплохие инструменты: Sqliteman, SQlite Designer или SQLite Manager.


doza_and
Почему вы взяли что их будет много?
Молод, зелен, категоричен . В нескольких найденных решениях, исходный код которых начал ковырять, используется либо SQLite, либо куча папок с текстовыми файлами, вложенных друг в друга. Второй метод мне не приглянулся, несмотря на простоту. С базой, всё же, надёжнее будет. Тем более, уже доводилось работать.

Ребят, вы уж извините меня за косноязычность в плане терминов и понятий. Не успел в полной мере освоить теорию.


doza_and
достаточно загрузить все данные в память поработать а потом все выгрузить
Вот это и ищу. То есть, повторюсь, моя задача стоит не в том, как записать дерево, нет. Пытаюсь понять, как лучше обработать имеющиеся в БД данные, чтобы можно было это дерево построить или производить какие-то манипуляции с ветками целиком (переносить на другие уровни, удалять). Может быть, вместо трёх полей level, parent, child можно использовать только parent, а может есть и другие способы.

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


P. S. В любом случае спасибо за то, что тратите своё время на помощь новичкам.

Отредактировано Rokot (Ноя. 15, 2014 18:49:17)

Офлайн

#9 Ноя. 15, 2014 22:09:24

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Организация дерева элементов

Я вам написал что реляционные базы неудобны для деревьев. Вторая строка в ссылке которую вам дали
“реляционные базы не приспособлены к хранению иерархических структур”
Вы ищете способ как загрузить такие данные. Вам дали работающий пример который загружающий именно ваши данные. Что вам еще надо? Зачем вы привязались к этим таблицам? Может у вас уже набиты таблицы?



Отредактировано doza_and (Ноя. 15, 2014 22:43:20)

Офлайн

#10 Ноя. 15, 2014 22:48:11

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

Организация дерева элементов

1. Использовать вложенные структуры данных, например словари + pickle для сериализации, возможно использование библиотек для вложенных структур https://pypi.python.org/pypi?%3Aaction=search&term=nested+dict&submit=search
2. Использовать форматы для сериализации и передачи данных: json/bson, xml, yaml.
3. Использовать графовые базы данных, например http://neo4j.com

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version