Python 排列组合生成

2020-09-13 22:12:37 +08:00
 zckun

老哥们, 请教一个问题, 是关于排列组合的, 前几天和老哥们讨论了一下, 能是能解决, 但感觉不太方便 看一个简单的例子应该就明白了.

<school type="primary|middle|university">
    <class number="1"/>
</school>

to

<school type="primary">
    <class number="1"/>
</school>

<school type="middle">
    <class number="1"/>
</school>

<school type="university">
    <class number="1"/>
</school>

目前是我这样做的, 用了一个模版 template

<school type="{school_type}">
    <class number="{class_number}"/>
</school>

代码和上面的学校例子有点不同,因为我的完整需求是这样的

<!-- base -->
<cross>
    <rule1 hint="rule 1" name="long" val1="30|60" val2="90|120" condition="1">
        <necessary_rule val1="60" val2="120" condition="1"/>
    </rule1>
</cross>

<!-- generator -->
<!-- 1 -->
<cross>
    <rule1 hint="rule 1" name="long" val1="30" val2="90" condition="1">
        <necessary_rule val1="60" val2="120" condition="1"/>
    </rule1>
</cross>

<!-- 2 -->
<cross>
    <rule1 hint="rule 1" name="long" val1="30" val2="120" condition="1">
        <necessary_rule val1="60" val2="120" condition="1"/>
    </rule1>
</cross>

<!-- 3 -->
<cross>
<rule1 hint="rule 1" name="long" val1="60" val2="90" condition="1">
    <necessary_rule val1="60" val2="120" condition="1"/>
</rule1>
</cross>

<!-- 4 -->
<cross>
<rule1 hint="rule 1" name="long" val1="60" val2="120" condition="1">
    <necessary_rule val1="60" val2="120" condition="1"/>
</rule1>
</cross>

代码

import xml.etree.ElementTree as ET
import itertools

from typing import Dict, Optional


def producer(rule, root_tag: Optional[str] = ''):
    rule_tag = rule.tag
    rule_temp = {}
    rule_attrib = rule.attrib
    for k, v in rule_attrib.items():
        k = f'{root_tag}{rule_tag}_{k}'
        if 'val' in v:
            v = rule_attrib.get(v)
        rule_temp[k] = v.split('|')
    return rule_temp


def params_parser():
    tree = ET.parse('rule.xml')
    rule_params = {}
    root = tree.getroot()
    for strategy in root:
        for rule in strategy:
            rule_params.update(**producer(rule))
            for child_rule in rule:
                rule_params.update(**producer(child_rule, root_tag=f'{rule.tag}_'))

    return rule_params


def rule_generator(rule_params: Dict):
    with open('rule_template.xml', encoding='utf-8') as f:
        template = f.read()

    for values in itertools.product(*rule_params.values()):
        params = dict(zip(rule_params.keys(), values))
        data = template.format(**params)
        print(data)


def main():
    rule_params = params_parser()
    rule_generator(rule_params)


if __name__ == '__main__':
    main()

我的思路是取出所有 tag 的 attrib,然后替换到模版. 上面的做法能解决我的问题,但这样每次都要弄一个模版我觉得很麻烦,有没有更简洁的办法

1581 次点击
所在节点    Python
7 条回复
reter
2020-09-13 22:40:37 +08:00
试一下用 html 模板库生成?比如 moko 或 jinja
应该两个循环就能完成
zckun
2020-09-13 22:50:58 +08:00
@reter 。。一时没想到 jinja
uti6770werty
2020-09-14 00:15:08 +08:00
搭车请教个问题,如果是以
testStr = string.Template('$who is $role')
如果 string 里面有过百个$模板变量,
是否可以以字典的方式传入替换?
testDict = {'who':'Tom,'role':'cat'}
这样去完成呢? 也不想启用 jinja 相对比较“重"利器去完成。。。
zckun
2020-09-14 00:23:28 +08:00
@uti6770werty 编程珠玑 26 页 3.2 格式信函编程和你这类似
Pagliacii
2020-09-14 00:25:54 +08:00
Pagliacii
2020-09-14 00:30:37 +08:00
@Pagliacii #5 s.substitute(d) 也是可以的
imn1
2020-09-14 00:56:12 +08:00
@uti6770werty #3
可以

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/706689

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX