只是一点背景:我正在创建一个程序,用户输入一个骨架文本,两个数字(下限和上限)以及一个单词列表。输出是对骨架文本的一系列修改。
示例输入:
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}对?
我不确定如何做到这一点。是否有任何与函数式编程或其他范例相关的东西可能对此有所帮助?问题是有点抽象,比任何东西更具风格/设计导向。
答案 0 :(得分: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))
答案 1 :(得分: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
你可以在理论上使用make_dict(dict, outer, inner)
或类似的东西重构dict创建,但我认为最终对于如此短的代码片段不太清楚,特别是考虑到你必须预处理以某种方式进行投注。
答案 2 :(得分: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.
如果您需要其中一个值为“static”,只需提供单个元素列表:
gen = generate("Player # likes @.", {'#': [1], '@': ['apples', 'bananas']})
请注意,这适用于任意数量的占位符:
gen = generate("Player # likes @ and can $", {
'#': range(1,3),
'@': ['apples', 'bananas'],
'$': ['swim', 'run', 'jump']
})