Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从层次结构创建嵌套列表_Python_Django_Data Structures - Fatal编程技术网

Python 如何从层次结构创建嵌套列表

Python 如何从层次结构创建嵌套列表,python,django,data-structures,Python,Django,Data Structures,我有一些UserInvites,其中invites具有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 因此,User1邀

我有一些UserInvites,其中invites具有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
因此,User1邀请了User2和User4;User2邀请了User3和User5

给定这些邀请的列表,例如[UserInvite1,UserInvite2,…],或者对它们进行迭代的另一种方法,如何生成表示这些邀请的层次嵌套列表

例如,从根User1开始,我想要一个嵌套列表:

>>> make_nest_list_from_invites([invites])
[User1, [User2, [User3, User5], User4]]
如果您熟悉Django,我正在尝试从我的邀请中获取一些层次结构的内容,我可以将这些内容提供给Django模板标记

很明显,这有点像树遍历,但我现在被难倒了。我尝试了一些递归的东西,但最终还是在一些地方进行了额外的嵌套

更新:我试过的例子 其中:

>>> tree_from_here(User1)
[<User: 1>, [[<User: 2>, [<User: 3>, <User: 5>]], <User: 4>]]
这对于我当前的用户集几乎是正确的,唯一的例外是嵌套在第二个元素中太深了

我正在努力:

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

我觉得它就像在盯着我的脸,但我不知道现在该如何回报正确的东西

我很难理解您关于嵌套结构表示的想法,但是经过大量思考和编写代码后,我相信我能理解,所以我猜这就是您想要的-代码和在线演示中的描述:-这是一个很好的挑战,thx:

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]]]

您已经有了一个很好的想法-遍历当前用户邀请的每个用户,然后递归这些用户邀请的每个用户,停止条件为:当to用户与您开始使用的根用户相同或不存在时。您不需要树的头吗?@Stephernauch您是在问我还是@Taylor?我认为树的根可以是相对的,例如感兴趣的用户ID,也可以是绝对的,例如第一个用户。但我不确定后者是否有效:如果第一个用户没有邀请任何人,而第二个用户在没有推荐的情况下加入怎么办?也许根节点在这里没有意义,这更像是一个图而不是一个树。@TaylorEdmiston有根的概念,没有用户没有其他用户的邀请。谢谢你的解释。您前面描述的似乎是我大声说出来的方式-但是将代码放在一起,然后对每个请求进行递归。。。这就是我绊倒的地方。我很快会发布一个更新和进步的例子。非常感谢!你的方法正是我想要的!从我最近的一次尝试中可以看出:我试图从一个用户开始,然后使用一个实用程序get_children从那里往下走。从邀请开始,就像你和我在原始问题中提到的那样,效果很好!再次感谢!哟!如果我可以补充一点,如果你想在大量邀请中有效地使用它,你可能应该在将邀请传递给嵌套调用之前减去邀请者覆盖的邀请,以避免开销查找
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]]]