回答我对树行走算法的一个问题
MLM downline distribution count
我想遍历整个用户树并打印节点,但我收到一条奇怪的错误消息:
TypeError: 'User' object is not iterable
这是我试图在树上行走的代码:
downlinestack = []
distributor=self
downlinestack += User.query(User.sponsor == distributor.key).fetch(99999999)
while downlinestack:
downline = downlinestack.pop()
logging.info('downline: %s' %str(downline))
for person in downline:
downlinestack.append(User.query(User.sponsor == person.key).fetch(99999999))
logging.info('person: %s' %str(person.key.id()))
我应该如何更改代码,以便它通过赞助商属性遍历用户树?
谢谢
我发现了一个递归解决方案,它看起来像这样:
def downline(self, person, team, teamlist):
firstline = User.query(User.sponsor == person.key).fetch(99999999)
if firstline:
for person in firstline:
teamlist.append(person)
newdownline = self.downline(person, team, teamlist)
team.append(newdownline)
return teamlist
def this_month_non_manager_silver(self):
silver = 0
today = date.today()
timeline = date(today.year, today.month, 1)
for person in self.downline(self, [], []):
logging.info('element:%s' % str(person.key.id()) )
orders = model.Order.all().filter('distributor_id =',
person.key.id()).filter('created >',
timeline).filter('status =', 'PAID'
).fetch(999999)
for order in orders:
for (idx, item) in enumerate(order.items):
purchase = model.Item.get_by_id(long(item.id()))
amount = int(order.amounts[idx])
silver = silver + amount * purchase.silver \
/ 1000.000
return silver
答案 0 :(得分:3)
该行
downlinestack += User.query(User.sponsor == distributor.key).fetch(99999999)
希望RHS返回一个列表以使用。{/ p>扩展downlinestack
>>> a = ['a']
>>> a += ['b']
>>> a
['a', 'b']
除非User.query()。fetch()返回一个列表,否则我怀疑你的意思是
downlinstack.append(downlinestack += User.query(User.sponsor == distributor.key).fetch(99999999))
我的另一个猜测是,无论你追加downlinestack
的是什么都不可迭代,所以下面的行失败了
for person in downline:
答案 1 :(得分:1)
为什么不只是两个嵌套的?
for downline in User.query(User.sponsor == distributor.key).fetch(99999999):
logging.info('downline: %s' %str(downline))
for person in downline:
downlinestack.append(User.query(User.sponsor == person.key).fetch(99999999))
logging.info('person: %s' %str(person.key.id()))
答案 2 :(得分:0)
让我通过逐行浏览代码来澄清:
downlinestack = []
distributor=self
downlinestack += User.query(User.sponsor == distributor.key).fetch(99999999)
首先,您没有告诉我们User.query
返回的内容。我假设它是一个用户对象列表。现在downlinestack
看起来像这样:[User1, User2, User3]
while downlinestack:
downline = downlinestack.pop()
现在downline
包含从堆栈末尾弹出的单个用户User3
。
logging.info('downline: %s' %str(downline))
for person in downline:
这是您的错误:User3
不可迭代。没有什么神秘之处:它不是那种对象。它不是可以依次迭代访问的项目集合。如果你想在这里迭代一些东西,你必须自己生成可迭代的。
有两种方法可以做到这一点。第一种是迭代User.query返回的列表:
distributor=self
downlinestack = User.query(User.sponsor == distributor.key).fetch(99999999)
while downlinestack:
top_person = downlinestack.pop()
logging.info('top_person: %s' %str(top_person))
for person in User.query(User.sponsor == top_person.key).fetch(99999999):
downlinestack.append(person)
您的另一个选择是将downlinestack
放入列表列表中:
distributor=self
downlinestack = [User.query(User.sponsor == distributor.key).fetch(99999999)]
while downlinestack:
downline_top = downlinestack.pop()
for person in downline_top:
downlinestack.append(User.query(User.sponsor == person.key).fetch(99999999))
logging.info('person: %s' %str(person.key.id()))
其中任何一个都应该有用。
我没有足够的上下文来测试上面的内容,但我创建了自己的简化测试方案,只是为了说明这确实有效。
>>> query_tree = {0: [1, 2, 3], 1: [4, 5], 2: [6], 3: [7, 8, 9, 10], 4: [],
5: [11, 12], 6: [], 7: [], 8: [13], 9: [], 10: [], 11: [14],
12: [], 13: [], 14: []}
>>> stack = query_tree[0][:] #make a copy to avoid changes to `query_tree`
>>> while stack:
... top_person = stack.pop()
... print top_person
... for person in query_tree[top_person]:
... stack.append(person)
...
3
10
9
8
13
7
2
6
1
5
12
11
14
4
正如您所看到的,这会在查询树中打印出每个人的id(root id为0除外)。
然后是另一种方法:
>>> stack = [query_tree[0]]
>>> while stack:
... top_person_list = stack.pop()
... for person in top_person_list:
... print person
... stack.append(query_tree[person])
...
1
2
3
7
8
9
10
13
6
4
5
11
12
14