如何在外循环完成后让内循环最后一次触发
How to get the inner loop to trigger one last time after outer loop is complete
我有两个列表:
- 第一个列表包含顶级名称信息;每个项目多个描述符
- 第二个列表包含第一个列表中项目的变体;每个项目还有多个描述符
外部(第一个)列表有三个项目; name1
、name2
和 name3
。还有一个 source
,但为了简单起见,我没有费心在示例中更改它。
内部(第二)列表包含外部列表的名称和来源,然后有自己的名称和来源。
最终结果应该是这样的:
name1 (source1)
===============
* [name1-foo1]: . "description1"
* [name1-foo2]: . "description2"
* [name1-foo3]: . "description3"
subname1 (subsource1)
---------------
* [name1-sub1-bar1]: . "description1"
* [name1-sub1-bar2]: . "description2"
* [name1-sub1-bar3]: . "description3"
subname2 (subsource1)
---------------
* [name1-sub2-bar1]: . "description1"
* [name1-sub2-bar2]: . "description2"
* [name1-sub2-bar3]: . "description3"
...
我的问题是我的外循环查找 name
和 source
中的更改作为打印 headers 的触发器并继续打印下一个内容。但是由于内部循环仅由 change 触发,当外部循环 运行 结束时,它不会 运行 内部循环最后一次到获得所有 sub-items.
import collections
OuterRecord = collections.namedtuple('OuterRecord',
'name, source, thing, level, description')
InnerRecord = collections.namedtuple('InnerRecord',
'name, source, in_name, in_source, thing, level, description')
o = [
OuterRecord('name1', 'source1', 'name1-foo1', 1, 'description1'),
OuterRecord('name1', 'source1', 'name1-foo2', 5, 'description2'),
OuterRecord('name1', 'source1', 'name1-foo3', 10, 'description3'),
OuterRecord('name2', 'source1', 'name2-foo1', 1, 'description1'),
OuterRecord('name2', 'source1', 'name2-foo2', 5, 'description2'),
OuterRecord('name2', 'source1', 'name2-foo3', 10, 'description3'),
OuterRecord('name3', 'source1', 'name3-foo1', 1, 'description1'),
OuterRecord('name3', 'source1', 'name3-foo2', 5, 'description2')
]
i = [
InnerRecord('name1', 'source1', 'subname1', 'subsource1', 'name1-sub1-bar1', 1, 'description1'),
InnerRecord('name1', 'source1', 'subname1', 'subsource1', 'name1-sub1-bar2', 1, 'description2'),
InnerRecord('name1', 'source1', 'subname1', 'subsource1', 'name1-sub1-bar3', 1, 'description3'),
InnerRecord('name1', 'source1', 'subname2', 'subsource1', 'name1-sub2-bar1', 1, 'description1'),
InnerRecord('name1', 'source1', 'subname2', 'subsource1', 'name1-sub2-bar2', 1, 'description2'),
InnerRecord('name1', 'source1', 'subname2', 'subsource1', 'name1-sub2-bar3', 1, 'description3'),
InnerRecord('name2', 'source1', 'subname3', 'subsource1', 'name2-sub3-bar1', 1, 'description1'),
InnerRecord('name2', 'source1', 'subname3', 'subsource1', 'name2-sub3-bar2', 1, 'description2'),
InnerRecord('name2', 'source1', 'subname3', 'subsource1', 'name2-sub3-bar2', 1, 'description3'),
InnerRecord('name3', 'source1', 'subname4', 'subsource1', 'name3-sub4-bar1', 1, 'description1'),
InnerRecord('name3', 'source1', 'subname4', 'subsource1', 'name3-sub4-bar2', 1, 'description2'),
InnerRecord('name3', 'source1', 'subname4', 'subsource1', 'name3-sub4-bar2', 1, 'description3'),
InnerRecord('name3', 'source1', 'subname5', 'subsource1', 'name3-sub5-bar1', 1, 'description1'),
InnerRecord('name3', 'source1', 'subname5', 'subsource1', 'name3-sub5-bar2', 1, 'description2'),
InnerRecord('name3', 'source1', 'subname5', 'subsource1', 'name3-sub5-bar3', 1, 'description3'),
InnerRecord('name3', 'source1', 'subname6', 'subsource1', 'name3-sub6-bar1', 1, 'description1'),
InnerRecord('name3', 'source1', 'subname6', 'subsource1', 'name3-sub6-bar2', 1, 'description2'),
InnerRecord('name3', 'source1', 'subname6', 'subsource1', 'name3-sub6-bar3', 1, 'description3'),
]
def loop_over(outer_list, inner_list):
current_outer_name = None
current_outer_source = None
current_inner_name = None
current_inner_source = None
for outer in outer_list:
if current_outer_name is None:
print('\n{} ({})'.format(outer.name, outer.source))
print('=' * 15)
current_outer_name = outer.name
current_outer_source = outer.source
if outer.name != current_outer_name or outer.source != current_outer_source:
for inner in [x for x in inner_list if x.name == current_outer_name and x.source == current_outer_source]:
if current_inner_name is None:
print('\n{} ({})'.format(inner.in_name, inner.in_source))
print('-' * 15)
current_inner_name = inner.in_name
current_inner_source = inner.in_source
if inner.in_name != current_inner_name or inner.in_source != current_inner_source:
print('\n{} ({})'.format(inner.in_name, inner.in_source))
print('-' * 15)
current_inner_name = inner.in_name
current_inner_source = inner.in_source
print('* [{}]: . "{}"'.format(inner.thing, inner.description))
print('\n{} ({})'.format(outer.name, outer.source))
print('=' * 15)
current_outer_name = outer.name
current_outer_source = outer.source
print('* [{}]: . "{}"'.format(outer.thing, outer.description))
loop_over(o, i)
所以我可以 运行 一旦一切都完成,内部循环再分开一次,但这闻起来很难闻。
是否有更好的方法来构造循环,以便一次性完成所有操作?
关于您的代码的一个有趣事实是,它看起来很有价值,可以检测更改。不幸的是,最后一个值没有机会被检测到,因为循环到此结束。
而是使用两个指针,一个用于当前,一个用于列表中的 下一个 值。使用这样的条件来检测下一个变化 (lookahead)
for index, outer in enumerate(outer_list):
next_outer_source = outer_list[index + 1] if index < len(outer_list) - 1 else None
show_outer_header = current_outer_name != outer.name or current_outer_source != outer.source
show_inner_values = next_outer_source is None or outer.name != next_outer_source.name or outer.source != next_outer_source.source
这是您的函数的清理副本:
def loop_over(outer_list, inner_list):
current_outer_name = None
current_outer_source = None
current_inner_name = None
current_inner_source = None
prev_outer_source = None
for index, outer in enumerate(outer_list):
next_outer_source = outer_list[index + 1] if index < len(outer_list) - 1 else None
show_outer_header = current_outer_name != outer.name or current_outer_source != outer.source
show_inner_values = next_outer_source is None or outer.name != next_outer_source.name or outer.source != next_outer_source.source
# print outer header
if show_outer_header:
print('\n{} ({})'.format(outer.name, outer.source))
print('=' * 15)
current_outer_name, current_outer_source = outer.name, outer.source
# print outer value
print('* [{}]: . "{}"'.format(outer.thing, outer.description))
# print inner values
if show_inner_values:
current_outer_name = outer.name
current_outer_source = outer.source
for inner in [x for x in inner_list if x.name == current_outer_name and x.source == current_outer_source]:
if current_inner_name is None:
print('\n{} ({})'.format(inner.in_name, inner.in_source))
print('-' * 15)
current_inner_name = inner.in_name
current_inner_source = inner.in_source
if inner.in_name != current_inner_name or inner.in_source != current_inner_source:
print('\n{} ({})'.format(inner.in_name, inner.in_source))
print('-' * 15)
current_inner_name = inner.in_name
current_inner_source = inner.in_source
print('* [{}]: . "{}"'.format(inner.thing, inner.description))
输出:
name1 (source1)
===============
* [name1-foo1]: . "description1"
* [name1-foo2]: . "description2"
* [name1-foo3]: . "description3"
subname1 (subsource1)
---------------
* [name1-sub1-bar1]: . "description1"
* [name1-sub1-bar2]: . "description2"
* [name1-sub1-bar3]: . "description3"
subname2 (subsource1)
---------------
* [name1-sub2-bar1]: . "description1"
* [name1-sub2-bar2]: . "description2"
* [name1-sub2-bar3]: . "description3"
name2 (source1)
===============
* [name2-foo1]: . "description1"
* [name2-foo2]: . "description2"
* [name2-foo3]: . "description3"
subname3 (subsource1)
---------------
* [name2-sub3-bar1]: . "description1"
* [name2-sub3-bar2]: . "description2"
* [name2-sub3-bar2]: . "description3"
name3 (source1)
===============
* [name3-foo1]: . "description1"
* [name3-foo2]: . "description2"
subname4 (subsource1)
---------------
* [name3-sub4-bar1]: . "description1"
* [name3-sub4-bar2]: . "description2"
* [name3-sub4-bar2]: . "description3"
subname5 (subsource1)
---------------
* [name3-sub5-bar1]: . "description1"
* [name3-sub5-bar2]: . "description2"
* [name3-sub5-bar3]: . "description3"
subname6 (subsource1)
---------------
* [name3-sub6-bar1]: . "description1"
* [name3-sub6-bar2]: . "description2"
* [name3-sub6-bar3]: . "description3"
鉴于冗长的数据结构,我预计效率并不是您真正想要的,因此这似乎是一种相当简洁易读的方式来获得您需要的内容:
def print_outer_and_inner(outer_recs, inner_recs):
for name, source in {(o_rec.name, o_rec.source): None for o_rec in outer_recs}:
print(f'{name} ({source})')
print('=' * 15)
for o_rec in outer_recs:
if o_rec.name == name:
print(f'* [{o_rec.thing}]: . "{o_rec.description}"')
print()
for sub_name, sub_source in {(i_rec.in_name, i_rec.in_source): None for i_rec in inner_recs}:
print(f'{sub_name} ({sub_source})')
print('-' * 15)
for i_rec in inner_recs:
if i_rec.in_name == sub_name:
print(f'* [{i_rec.thing}]: . "{i_rec.description}"')
print()
print_outer_and_inner(o, i)
主要的缺点是它在每个列表上循环了很多次,但它给你的是简洁,而且可以说是可读性。
我有两个列表:
- 第一个列表包含顶级名称信息;每个项目多个描述符
- 第二个列表包含第一个列表中项目的变体;每个项目还有多个描述符
外部(第一个)列表有三个项目; name1
、name2
和 name3
。还有一个 source
,但为了简单起见,我没有费心在示例中更改它。
内部(第二)列表包含外部列表的名称和来源,然后有自己的名称和来源。
最终结果应该是这样的:
name1 (source1)
===============
* [name1-foo1]: . "description1"
* [name1-foo2]: . "description2"
* [name1-foo3]: . "description3"
subname1 (subsource1)
---------------
* [name1-sub1-bar1]: . "description1"
* [name1-sub1-bar2]: . "description2"
* [name1-sub1-bar3]: . "description3"
subname2 (subsource1)
---------------
* [name1-sub2-bar1]: . "description1"
* [name1-sub2-bar2]: . "description2"
* [name1-sub2-bar3]: . "description3"
...
我的问题是我的外循环查找 name
和 source
中的更改作为打印 headers 的触发器并继续打印下一个内容。但是由于内部循环仅由 change 触发,当外部循环 运行 结束时,它不会 运行 内部循环最后一次到获得所有 sub-items.
import collections
OuterRecord = collections.namedtuple('OuterRecord',
'name, source, thing, level, description')
InnerRecord = collections.namedtuple('InnerRecord',
'name, source, in_name, in_source, thing, level, description')
o = [
OuterRecord('name1', 'source1', 'name1-foo1', 1, 'description1'),
OuterRecord('name1', 'source1', 'name1-foo2', 5, 'description2'),
OuterRecord('name1', 'source1', 'name1-foo3', 10, 'description3'),
OuterRecord('name2', 'source1', 'name2-foo1', 1, 'description1'),
OuterRecord('name2', 'source1', 'name2-foo2', 5, 'description2'),
OuterRecord('name2', 'source1', 'name2-foo3', 10, 'description3'),
OuterRecord('name3', 'source1', 'name3-foo1', 1, 'description1'),
OuterRecord('name3', 'source1', 'name3-foo2', 5, 'description2')
]
i = [
InnerRecord('name1', 'source1', 'subname1', 'subsource1', 'name1-sub1-bar1', 1, 'description1'),
InnerRecord('name1', 'source1', 'subname1', 'subsource1', 'name1-sub1-bar2', 1, 'description2'),
InnerRecord('name1', 'source1', 'subname1', 'subsource1', 'name1-sub1-bar3', 1, 'description3'),
InnerRecord('name1', 'source1', 'subname2', 'subsource1', 'name1-sub2-bar1', 1, 'description1'),
InnerRecord('name1', 'source1', 'subname2', 'subsource1', 'name1-sub2-bar2', 1, 'description2'),
InnerRecord('name1', 'source1', 'subname2', 'subsource1', 'name1-sub2-bar3', 1, 'description3'),
InnerRecord('name2', 'source1', 'subname3', 'subsource1', 'name2-sub3-bar1', 1, 'description1'),
InnerRecord('name2', 'source1', 'subname3', 'subsource1', 'name2-sub3-bar2', 1, 'description2'),
InnerRecord('name2', 'source1', 'subname3', 'subsource1', 'name2-sub3-bar2', 1, 'description3'),
InnerRecord('name3', 'source1', 'subname4', 'subsource1', 'name3-sub4-bar1', 1, 'description1'),
InnerRecord('name3', 'source1', 'subname4', 'subsource1', 'name3-sub4-bar2', 1, 'description2'),
InnerRecord('name3', 'source1', 'subname4', 'subsource1', 'name3-sub4-bar2', 1, 'description3'),
InnerRecord('name3', 'source1', 'subname5', 'subsource1', 'name3-sub5-bar1', 1, 'description1'),
InnerRecord('name3', 'source1', 'subname5', 'subsource1', 'name3-sub5-bar2', 1, 'description2'),
InnerRecord('name3', 'source1', 'subname5', 'subsource1', 'name3-sub5-bar3', 1, 'description3'),
InnerRecord('name3', 'source1', 'subname6', 'subsource1', 'name3-sub6-bar1', 1, 'description1'),
InnerRecord('name3', 'source1', 'subname6', 'subsource1', 'name3-sub6-bar2', 1, 'description2'),
InnerRecord('name3', 'source1', 'subname6', 'subsource1', 'name3-sub6-bar3', 1, 'description3'),
]
def loop_over(outer_list, inner_list):
current_outer_name = None
current_outer_source = None
current_inner_name = None
current_inner_source = None
for outer in outer_list:
if current_outer_name is None:
print('\n{} ({})'.format(outer.name, outer.source))
print('=' * 15)
current_outer_name = outer.name
current_outer_source = outer.source
if outer.name != current_outer_name or outer.source != current_outer_source:
for inner in [x for x in inner_list if x.name == current_outer_name and x.source == current_outer_source]:
if current_inner_name is None:
print('\n{} ({})'.format(inner.in_name, inner.in_source))
print('-' * 15)
current_inner_name = inner.in_name
current_inner_source = inner.in_source
if inner.in_name != current_inner_name or inner.in_source != current_inner_source:
print('\n{} ({})'.format(inner.in_name, inner.in_source))
print('-' * 15)
current_inner_name = inner.in_name
current_inner_source = inner.in_source
print('* [{}]: . "{}"'.format(inner.thing, inner.description))
print('\n{} ({})'.format(outer.name, outer.source))
print('=' * 15)
current_outer_name = outer.name
current_outer_source = outer.source
print('* [{}]: . "{}"'.format(outer.thing, outer.description))
loop_over(o, i)
所以我可以 运行 一旦一切都完成,内部循环再分开一次,但这闻起来很难闻。
是否有更好的方法来构造循环,以便一次性完成所有操作?
关于您的代码的一个有趣事实是,它看起来很有价值,可以检测更改。不幸的是,最后一个值没有机会被检测到,因为循环到此结束。
而是使用两个指针,一个用于当前,一个用于列表中的 下一个 值。使用这样的条件来检测下一个变化 (lookahead)
for index, outer in enumerate(outer_list):
next_outer_source = outer_list[index + 1] if index < len(outer_list) - 1 else None
show_outer_header = current_outer_name != outer.name or current_outer_source != outer.source
show_inner_values = next_outer_source is None or outer.name != next_outer_source.name or outer.source != next_outer_source.source
这是您的函数的清理副本:
def loop_over(outer_list, inner_list):
current_outer_name = None
current_outer_source = None
current_inner_name = None
current_inner_source = None
prev_outer_source = None
for index, outer in enumerate(outer_list):
next_outer_source = outer_list[index + 1] if index < len(outer_list) - 1 else None
show_outer_header = current_outer_name != outer.name or current_outer_source != outer.source
show_inner_values = next_outer_source is None or outer.name != next_outer_source.name or outer.source != next_outer_source.source
# print outer header
if show_outer_header:
print('\n{} ({})'.format(outer.name, outer.source))
print('=' * 15)
current_outer_name, current_outer_source = outer.name, outer.source
# print outer value
print('* [{}]: . "{}"'.format(outer.thing, outer.description))
# print inner values
if show_inner_values:
current_outer_name = outer.name
current_outer_source = outer.source
for inner in [x for x in inner_list if x.name == current_outer_name and x.source == current_outer_source]:
if current_inner_name is None:
print('\n{} ({})'.format(inner.in_name, inner.in_source))
print('-' * 15)
current_inner_name = inner.in_name
current_inner_source = inner.in_source
if inner.in_name != current_inner_name or inner.in_source != current_inner_source:
print('\n{} ({})'.format(inner.in_name, inner.in_source))
print('-' * 15)
current_inner_name = inner.in_name
current_inner_source = inner.in_source
print('* [{}]: . "{}"'.format(inner.thing, inner.description))
输出:
name1 (source1)
===============
* [name1-foo1]: . "description1"
* [name1-foo2]: . "description2"
* [name1-foo3]: . "description3"
subname1 (subsource1)
---------------
* [name1-sub1-bar1]: . "description1"
* [name1-sub1-bar2]: . "description2"
* [name1-sub1-bar3]: . "description3"
subname2 (subsource1)
---------------
* [name1-sub2-bar1]: . "description1"
* [name1-sub2-bar2]: . "description2"
* [name1-sub2-bar3]: . "description3"
name2 (source1)
===============
* [name2-foo1]: . "description1"
* [name2-foo2]: . "description2"
* [name2-foo3]: . "description3"
subname3 (subsource1)
---------------
* [name2-sub3-bar1]: . "description1"
* [name2-sub3-bar2]: . "description2"
* [name2-sub3-bar2]: . "description3"
name3 (source1)
===============
* [name3-foo1]: . "description1"
* [name3-foo2]: . "description2"
subname4 (subsource1)
---------------
* [name3-sub4-bar1]: . "description1"
* [name3-sub4-bar2]: . "description2"
* [name3-sub4-bar2]: . "description3"
subname5 (subsource1)
---------------
* [name3-sub5-bar1]: . "description1"
* [name3-sub5-bar2]: . "description2"
* [name3-sub5-bar3]: . "description3"
subname6 (subsource1)
---------------
* [name3-sub6-bar1]: . "description1"
* [name3-sub6-bar2]: . "description2"
* [name3-sub6-bar3]: . "description3"
鉴于冗长的数据结构,我预计效率并不是您真正想要的,因此这似乎是一种相当简洁易读的方式来获得您需要的内容:
def print_outer_and_inner(outer_recs, inner_recs):
for name, source in {(o_rec.name, o_rec.source): None for o_rec in outer_recs}:
print(f'{name} ({source})')
print('=' * 15)
for o_rec in outer_recs:
if o_rec.name == name:
print(f'* [{o_rec.thing}]: . "{o_rec.description}"')
print()
for sub_name, sub_source in {(i_rec.in_name, i_rec.in_source): None for i_rec in inner_recs}:
print(f'{sub_name} ({sub_source})')
print('-' * 15)
for i_rec in inner_recs:
if i_rec.in_name == sub_name:
print(f'* [{i_rec.thing}]: . "{i_rec.description}"')
print()
print_outer_and_inner(o, i)
主要的缺点是它在每个列表上循环了很多次,但它给你的是简洁,而且可以说是可读性。