2

只是一点背景:我正在制作一个程序,用户输入一个框架文本、两个数字(下限和上限)和一个单词列表。输出是对骨架文本的一系列修改。

样本输入:

text = "Player # likes @." (replace # with inputted integers and @ with words in list)
lower = 1
upper = 3
list = "apples, bananas, oranges"

用户可以选择先迭代数字:

Player 1 likes apples.
Player 2 likes apples.
Player 3 likes apples.

或者先说一句话​​:

Player 1 likes apples.
Player 1 likes bananas.
Player 1 likes oranges.

我选择通过基于数字键(用户输入的整数)或单词键(来自输入列表中的单词)创建不同类型的字典来拆分这两种输出方法,然后迭代字典中的值。

以下是两种类型的字典创建:

def numkey(dict): # {1: ['Player 1 likes apples', 'Player 1 likes...' ] }

    text, lower, upper, list = input_sort(dict)
    d = {}

    for num in range(lower,upper+1):
        l = []
        for i in list:
            l.append(text.replace('#', str(num)).replace('@', i))
        d[num] = l
    return d

def wordkey(dict): # {'apples': ['Player 1 likes apples', 'Player 2 likes apples'..] }

    text, lower, upper, list = input_sort(dict)
    d = {}

    for i in list:
        l = []
        for num in range(lower,upper+1):
            l.append(text.replace('#', str(num)).replace('@', i))
        d[i] = l
    return d

很好,我有两个单独的函数来创建不同类型的字典,但我看到两者之间有很多重复。有什么方法可以让我创建一个字典函数并将不同的值传递给它,这会改变嵌套 for 循环的顺序以创建我正在寻找的特定 {key : value} 对?

我不确定如何做到这一点。有什么与函数式编程或其他范式相关的东西可能对此有所帮助吗?这个问题有点抽象,比任何东西都更注重风格/设计。

4

3 回答 3

2

您不需要字典来生成输出。你可以使用类似的东西:

import itertools

numbers = range(lower, upper + 1)
words = "a, b, c".split(", ")

data = (numbers, words) if numbers_first else (words, numbers)
for n, w in itertools.product(*data):
    if not numbers_first: n, w = w, n
    print("Player %d likes %s." % (n, w))

为了避免if循环内部,您可以动态生成格式字符串,例如:

template = "Player # likes @."
subs = ("{n}", "{w}") if numbers_first else ("{w}", "{n}")
format = make_format(template, subs) # escape {}, replace # and @

# ...
for n, w in product(*data):
    print(format.format(n=n, w=w))
于 2012-06-03T17:00:44.860 回答
1

我认为在这种情况下,与其将两个进程强制为一个函数,不如让每个函数更短:

def numkey(dict):
    text, lower, upper, list = input_sort(dict)
    d = {x: [text.replace('#',str(x)).replace('@',item) 
            for item in list.split(', ')] for x in xrange(lower,upper+1)}
    return d

def wordkey(dict):
    text, lower, upper, list = input_sort(dict)
    d = {item: [text.replace('#',str(x)).replace('@',item) 
            for x in xrange(lower,upper+1)] for item in list.split(', ')}
    return d

理论上,您可以使用 a 或类似的东西重构 dict 创建make_dict(dict, outer, inner),但我认为对于如此短的代码位最终不太清楚,特别是考虑到您必须以某种方式预处理 int。

于 2012-06-03T16:55:21.357 回答
1

这是一个更通用的方法:

from itertools import product

def generate(skeleton, replacements):
    values = (product([k], v) for k, v in replacements.items())
    for p in product(*values):
        s = skeleton
        for a, b in p:
            s = s.replace(a, str(b))
        yield s

replacements应为字典{placeholder: list of values},例如:

gen = generate("Player # likes @.", {'#': range(1,3), '@': ['apples', 'bananas']})    
for phrase in gen:
    print phrase

印刷

Player 1 likes apples.
Player 2 likes apples.
Player 1 likes bananas.
Player 2 likes bananas.

如果您需要其中一个值是“静态的”,只需提供一个单元素列表:

gen = generate("Player # likes @.", {'#': [1], '@': ['apples', 'bananas']})    

请注意,这适用于任意数量的占位符:

gen = generate("Player # likes @ and can $", {
    '#': range(1,3), 
    '@': ['apples', 'bananas'],
    '$': ['swim', 'run', 'jump']
})    
于 2012-06-03T18:00:27.873 回答