Как создать вложенный список из иерархии - PullRequest
0 голосов
/ 10 июня 2018

У меня есть несколько UserInvites, где приглашение имеет from и to Свойства пользователя.

Например,

UserInvite1.from = User1
UserInvite1.to = User2

UserInvite1b.from = User1
UserInvite1b.to = User4

UserInvite2.from = User2
UserInvite2.to = User3

UserInvite3.from = User2
UserInvite3.to = User5

Таким образом, Пользователь1 пригласил Пользователя2 и Пользователя4;Пользователь2 пригласил Пользователя3 и Пользователя5.

Учитывая список этих приглашений, например, [UserInvite1, UserInvite2, ... ], или другое средство итерации по ним (?), Как я могу сгенерировать «иерархический» (вложенный) список, представляющий этипригласил?

Например, начиная с «root» User1, я бы хотел, чтобы вложенный список был таким:

>>> make_nest_list_from_invites([invites])
[User1, [User2, [User3, User5], User4]]

Если вы знакомы с Django, я пытаюсь получить отмои "приглашения" к чему-то иерархическому, что я могу передать тегу шаблона Django unordered_list

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

ОБНОВЛЕНИЕ: Пример чего-то, что я попробовал

def tree_from_here(user):
    children = get_children(user)
    if children:
        return [user, [tree_from_here(c) for c in children]]
    else:
        return user

, что дает:

>>> tree_from_here(User1)
[<User: 1>, [[<User: 2>, [<User: 3>, <User: 5>]], <User: 4>]]

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

Я пытаюсь:

[<User: 1>, [<User: 2>, [<User: 3>, <User: 5>], <User: 4>]]

Я чувствую, что это смотрит мне в лицо, но я не уверен, как вернуть правильную вещь в данный момент.

1 Ответ

0 голосов
/ 10 июня 2018

Мне было трудно понять вашу идею об этой репрезентации вложенной структуры, но после долгих размышлений и написания кода я уверен, что понимаю, поэтому я думаю, что это то, что вам нужно - описание в коде идемо-версия здесь: https://repl.it/repls/EarlyWeeklyThings - это был хороший вызов, спасибо:)

from pprint import pprint

# dummy user class
class User(object):
  def __init__(self, user_id):
    self.user_id = user_id
  def __repr__(self):
    return "User{}".format(self.user_id)

# dummy invite class 
class UserInvite(object):
  def __init__(self, from_user, to_user):
    self.from_user = from_user
    self.to_user = to_user
  def __repr__(self):
    return "From {} to {}".format(self.from_user, self.to_user)

# create 10 dummy users to create invites
users = [User(user_id) for user_id in range(1,11)]

# use natural numbers to reflect invites
# adjust in list comprehension
invite_map = (
  (1, 3), (1, 5), 
  (2, 4), (2, 6),
  (3, 7), (3, 8),
  (4, 9),
  (9, 10)
)

# create invitations based on the invite_map, fix natural numbers
example_invites = [
  UserInvite(users[inviter-1], users[invitee-1]) for inviter, invitee in invite_map
]

pprint(example_invites)
# =>
# [From User1 to User3,
#  From User1 to User5,
#  From User2 to User4,
#  From User2 to User6,
#  From User3 to User7,
#  From User3 to User8,
#  From User4 to User9,
#  From User9 to User10]

def get_nested_invites(invites, invited_by=None):
  result = []
  if not invited_by:
    # Assume that initial inviters were not invited by anyone
    # Use set comprehensions to avoid duplicates and for performance
    invitees = {invite.to_user for invite in invites}
    inviters = {invite.from_user for invite in invites if invite.from_user not in invitees}
  else:
    # Get the next potential inviters given their inviter
    # Use set comprehension to avoid duplicates and for performance
    inviters = {invite.to_user for invite in invites if invite.from_user == invited_by}
  for inviter in inviters:
    # Add the invited user/potential inviter 
    result.append(inviter)
    # Let's get nesty
    invitees = get_nested_invites(invites, inviter)
    if invitees:
      result.append(invitees)
  return result

pprint(get_nested_invites(example_invites))
# =>
# [User1,
#  [User3, [User7, User8], User5],
#  User2,
#  [User6, User4, [User9, [User10]]]]

pprint(get_nested_invites(example_invites, users[1]))
# =>
# [User6, User4, [User9, [User10]]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...