2013-07-05 3 views
0

У меня есть список dicts, который выглядит примерно так:Построение списка с родитель-ребенок зависимости

list = [{'parent': u'#5963','id': 5962},{'parent': u'','id': 5963}, 
{'parent': u'#5963', 'id': 5964}, {'parent': u'#5966', 'id': 5967}, 
{'parent': u'#5963','id': 5966}, {'parent': u'#5962','id': 5968} ] 

Фактические dicts немного сложнее - у них есть несколько ключей и значений.

Как вы можете видеть - каждый dict имеет «родительский» ключ, который сообщает нам идентификатор родительского элемента и ключ «id».

Теперь вопрос заключается в следующем: возможно ли создать новый список (или отсортировать его) таким образом, чтобы все dicts помещались в родительско-дочерний путь?

Таким образом, новый ДИКТ будет:

[{'parent': u'','id': 5963},{'parent': u'#5963','id': 5962}, 
{'parent': u'#5962','id': 5968}, {'parent': u'#5963', 'id': 5964}, 
{'parent': u'#5963','id': 5966}, {'parent': u'#5966', 'id': 5967} ] 

PS: Там может быть не корневые элементы (элементы с ключом «родительского» = «»)
PPS: Родительский элемент не могут иметь более 1-2 уровней детей

+2

Я не понимаю. Что значит «родитель-ребенок»? Или другой вопрос: что вы пытаетесь выполнить? Я уверен, вы можете использовать дерево, чтобы избавиться от этих проблем ... – tamasgal

+0

Я получаю первый список в результате SQL-запроса. Затем он передается шаблону для построения таблицы. Шаблон использует элементы списка для создания строк таблицы. Теперь мне нужно - переупорядочить этот список так, чтобы итоговая таблица имела иерархию, таким образом, родительский путь. – konart

ответ

1

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

def build_tree(l): 
    exists = set(map(lambda x : x['id'], l)) 

    tops = [] 
    children = {} 
    for e in l: 
     parent = e['parent'] 
     if not parent: 
      tops.append(e) 
      continue 

     parent = int(parent[1:]) 
     if parent not in exists: 
      tops.append(e) 
      continue 

     if parent in children: 
      children[parent].append(e) 
     else: 
      children[parent] = [ e ] 

    return children, tops 

Затем сделать глубину первого обхода этого дерева с рекурсивной функцией:

def build_list(children, top): 
    l = [ top ] 
    if top['id'] in children: 
     for child in children[top['id']]: 
      l += build_list(children, child) 
    return l 

Первая функция даст вам структуру дети/отношение, а второй позволит вам создать список для каждого возможного верхнего узла.

Теперь вы можете отсортировать список, используя эти две функции:

l = [{'parent': u'#5963','id': 5962},{'parent': u'','id': 5963}, 
{'parent': u'#5963', 'id': 5964}, {'parent': u'#5966', 'id': 5967}, 
{'parent': u'#5963','id': 5966}, {'parent': u'#5962','id': 5968} ] 
children, tops = build_tree(l) 
for top in tops: 
    print build_list(children, top) 
# outputs : [{'id': 5963, 'parent': u''}, {'id': 5962, 'parent': u'#5963'}, 
# {'id': 5968, 'parent': u'#5962'}, {'id': 5964, 'parent': u'#5963'}, 
# {'id': 5966, 'parent': u'#5963'}, {'id': 5967, 'parent': u'#5966'}] 

Если удалить узел 5963, который даст:

[{'id': 5962, 'parent': u'#5963'}, {'id': 5968, 'parent': u'#5962'}] 
[{'id': 5964, 'parent': u'#5963'}] 
[{'id': 5966, 'parent': u'#5963'}, {'id': 5967, 'parent': u'#5966'}] 
+0

Что делать, если нет верхнего узла? (Нет dict с «родительским» ключом, который равен '') – konart

+0

@konart мой текущий код не работает в этом случае, но каковы данные, когда «нет родителя»? это потому, что дети ссылаются на не существующих родителей? или у вас есть петли в отношении родителя/ребенка? – Guillaume

+0

Предположим, мы говорим о некоторой системе отслеживания времени с билетами (один билет = одна задача). Каждая задача может иметь некоторые подзадачи. Задача верхнего уровня может принадлежать одному пользователю, но суб-таки кем-то другим. Когда владелец главной задачи запрашивает принадлежащие ему задачи, он получает список, похожий на тот, который указан в моем вопросе, но когда список запрашивается пользователем, которому принадлежат только подзадачи, список, который он увидит, будет таким же, кроме верхней задачи (верхний узел в вашем коде). Таким образом, у всех dicts будет некоторый родитель, но единого корня не будет. – konart

Смежные вопросы