此代码块有效 - 它循环遍历具有重复数据集的文件 并提取每组的5条信息中的每一条。
但我知道当前的因子分解效率并不高,因为它是循环的 通过每条线找到每条线。
想知道一些python专家能否提供更好的方法来更有效地做到这一点。
def parse_params(num_of_params,lines):
for line in lines:
for p in range(1,num_of_params + 1,1):
nam = "model.paramName "+str(p)+" "
par = "model.paramValue "+str(p)+" "
opt = "model.optimizeParam "+str(p)+" "
low = "model.paramLowerBound "+str(p)+" "
upp = "model.paramUpperBound "+str(p)+" "
keys = [nam,par,opt,low,upp]
for key in keys:
if key in line:
a,val = line.split(key)
if key == nam: names.append(val.rstrip())
if key == par: params.append(val.rstrip())
if key == opt: optimize.append(val.rstrip())
if key == upp: upper.append(val.rstrip())
if key == low: lower.append(val.rstrip())
print "Names = ",names
print "Params = ",params
print "Optimize = ",optimize
print "Upper = ",upper
print "Lower = ",lower
答案 0 :(得分:2)
虽然这不能回答你的问题(其他答案正在解决这个问题)但是在做与你正在做的事情相似的事情上帮助了我很多的事情List Comprehensions。它们允许您以简洁和(我认为)易于阅读的方式构建列表。
例如,下面的代码使用您尝试获取的值构建一个二维数组。 some_funct
这里有一个小正则表达式,如果我这样做,它使用键中最后一个空格的索引作为参数,并向前看以收集你想要在行中获得的值(与当前正在查看的键对应的值)并将其附加到seen_keys 2D数组中的正确索引。
罗嗦,是的,但是如果你得到列表理解并且你能够构建正则表达式来做到这一点,你就会有一个很好的,简洁的解决方案。
keys = ["model.paramName ","model.paramValue ","model.optimizeParam ""model.paramLowerBound ","model.paramUpperBound "]
for line in lines:
seen_keys = [[],[],[],[],[]]
[seen_keys[keys.index(k)].some_funct(line.index(k) for k in keys if k in line]
答案 1 :(得分:1)
那里有很多重复,如果你添加了另一个key
或param
,你将不得不在很多地方添加它,这使你很容易出错。你想要做的就是削减所有重复的地方并使用某种数据模型,例如dict
。
其他一些人提供了一些很好的例子,所以我会在这里留下我的答案给你一些思考。
答案 2 :(得分:1)
看到预期的格式并不容易。从我所看到的,格式如下:
lines = [
"model.paramName 1 foo",
"model.paramValue 2 bar",
"model.optimizeParam 3 bat",
"model.paramLowerBound 4 zip",
"model.paramUpperBound 5 ech",
"model.paramName 1 foo2",
"model.paramValue 2 bar2",
"model.optimizeParam 3 bat2",
"model.paramLowerBound 4 zip2",
"model.paramUpperBound 5 ech2",
]
如果每行中有多个值,我看不到上面的代码。这意味着除非我遗漏了某些东西,否则数字并不重要。在这种情况下,这非常容易:
import re
def parse_params(num_of_params,lines):
key_to_collection = {
"model.paramName":names,
"model.paramValue":params,
"model.optimizeParam":optimize,
"model.paramLowerBound":upper,
"model.paramUpperBound":lower,
}
reg = re.compile(r'(.+?) (\d) (.+)')
for line in lines:
m = reg.match(line)
key, digit, value = m.group(1, 2, 3)
key_to_collection[key].append(value)
答案 3 :(得分:1)
从您的代码中看并不完全明显,但看起来每条线最多只能有一个“命中”;如果确实如此,那么就像:
import re
def parse_params(num_of_params, lines):
sn = 'Names Params Optimize Upper Lower'.split()
ks = '''paramName paramValue optimizeParam
paramLowerBound paramUpperBound'''.split()
vals = dict((k, []) for k in ks)
are = re.compile(r'model\.(%s) (\d+) (.*)' % '|'.join(ks))
for line in lines:
mo = are.search(line)
if not mo: continue
p = int(mo.group(2))
if p < 1 or p > num_of_params: continue
vals[mo.group(1)].append(mo.group(3).rstrip())
for k, s in zip(ks, sn):
print '%-8s =' % s,
print vals[k]
可能有效 - 我用一些代码对它进行了如下操作:
if __name__ == '__main__':
lines = '''model.paramUpperBound 1 ZAP
model.paramLowerBound 1 zap
model.paramUpperBound 5 nope'''.splitlines()
parse_params(2, lines)
它会发出
Names = []
Params = []
Optimize = []
Upper = ['zap']
Lower = ['ZAP']
我认为这是你想要的(如果某些细节必须有所不同,请准确说明它们是什么,让我们看看我们是否可以解决它。)
两个关键想法是:使用dict
代替大量if
s;使用re
将“以下任何可能性”与re模式中的带括号的组匹配,以捕获感兴趣的位(model.
之后的关键字,此后的整数,以及“值”这是行的其余部分),而不是大量的if x in y
检查和字符串操作。
答案 4 :(得分:1)
OP中给出的代码每行进行多次测试,以尝试匹配预期的值集,每个值都是动态构建的。我们可以使用正则表达式来尝试以更便宜(更健壮)的方式进行匹配,而不是为每一行构造paramValue1
,paramValue2
等。
这是我的代码片段,摘自已发布的一些想法。这允许您向key_to_collection
字典添加新关键字,而不必更改任何其他内容。
import re
def parse_params(num_of_params, lines):
pattern = re.compile(r"""
model\.
(.+) # keyword
(\d+) # index to keyword
[ ]+ # whitespace
(.+) # value
""", re.VERBOSE)
key_to_collection = {
"paramName": names,
"paramValue": params,
"optimizeParam": optimize,
"paramLowerBound": upper,
"paramUpperBound": lower,
}
for line in lines:
match = pattern.match(line)
if not match:
print "Invalid line: " + line
elif match[1] not in key_to_collection:
print "Invalid key: " + line
# Not sure if you really care about enforcing this
elif match[2] > num_of_params:
print "Invalid param: " + line
else:
key_to_collection[match[1]].append(match[3])
完全披露:我没有编译/测试过这个。
答案 5 :(得分:1)
你确定parse_params是瓶颈吗?你有没有想过你的应用程序?
import re
from collections import defaultdict
names = ("paramName paramValue optimizeParam "
"paramLowerBound paramUpperBound".split())
stmt_regex = re.compile(r'model\.(%s)\s+(\d+)\s+(.*)' % '|'.join(names))
def parse_params(num_of_params, lines):
stmts = defaultdict(list)
for m in (stmt_regex.match(s) for s in lines):
if m and 1 <= int(m.group(2)) <= num_of_params:
stmts[m.group(1)].append(m.group(3).rstrip())
for k, v in stmts.iteritems():
print "%s = %s" % (k, ' '.join(v))
答案 6 :(得分:0)
当然可以提高效率。但是,说实话,除非这个函数每秒被调用数百次,或者在数千行上工作,是否有必要呢?
我会更关心明确发生了什么......目前,我在这方面还不太清楚。
只要注意它,输入看起来像这样:
model.paramName 1 a model.paramValue 1 B model.optimizeParam 1 C model.paramLowerBound 1 D model.paramUpperBound 1 E model.paramName 2 F model.paramValue 2 G model.optimizeParam 2 H model.paramLowerBound 2我model.paramUpperBound 2 J
你想要的输出似乎是这样的:
Names = AF Params = BG etc...
现在,既然我的输入肯定与你的输入不匹配,输出也可能会关闭,但我认为我有这个要点。
有几点。首先,将多少参数传递给函数是否重要?例如,如果输入有两组参数,我是否只想读取这两个参数,或者是否有必要允许该函数只读取一个?例如,您的代码允许我调用parse_params(1,1)
并让它只读取来自同一输入的以1结尾的参数。如果这实际上不是一个要求,你可以跳过很大一部分代码。
第二,仅阅读给定参数是否重要?例如,如果我有一个名为'paramFoo'的参数,那么如果我读它会不好?您还可以通过抓取所有参数(无论其名称如何)并提取其值来简化过程。
def parse_params(input):
parameter_list = {}
param = re.compile(r"model\.([^ ]+) [0-9]+ ([^ ]+)")
each_parameter = param.finditer(input)
for match in each_parameter:
key = match[0]
value = match[1]
if not key in paramter_list:
parameter_list[key] = []
parameter_list[key].append(value)
return parameter_list
在这种情况下,输出将是这样的:
{'paramName':[A,F],'paramValue':[B,G],'optimizeParam':[C,H]等......}
注意:我不太了解Python,我是一个Ruby人,所以我的语法可能会关闭。道歉。