【发布时间】:2018-02-01 18:12:43
【问题描述】:
我有参与者调查数据,其中包含每个变量的变量名称、它在该观察中的值以及提出该问题所需的条件(如果先前的答案确定某个问题不适用,则参与者不会提示)。我的任务之一是将表示 N/A 的空白与表示已询问但未回答的提示的空白区分开来。遗憾的是,我们的数据采集工具中的导出功能不提供此功能。
为了解决这个问题,我将每个变量分支的条件与记录的观察结果进行比较,并查看是否应该显示提示。这可能会让人感到困惑,例如,想象一下主题 A 的记录:
Variable Name | Observation Value | Branching Logic
foo | 5 |
bar | 2 | foo != 2
baz | 7 | foo < 10 or bar == 5
无论如何都会出现foo 的提示;将显示bar 的提示,因为foo = 5 满足其条件foo != 2,同样会观察到baz。我将其视为 pandas 数据框,因此在构建模块的玩具版本时,我使用 dict 来表示测试数据。我几乎让它工作了,但缺少一件:嵌套括号。
有很多类似的问题(例如pyparsing and line breaks),我在处理逻辑符号的 PyParsing 文档中找到了一个非常相似的示例,但是我不擅长 python,并且在使用多个类时遇到了麻烦,子类等。我可以将其用作以下内容的起点:
import pyparsing as pp
test_data = {
'a' : 3,
'b' : 6,
'c' : 2,
'd' : 4
}
# Functions applied by parser
def toInt(x):
return [int(k) for k in x]
def useKey(x):
try: return [test_data[k] for k in x]
except KeyError: print("Value not a key:", x)
def checkCond(parsed):
allinone = parsed[0]
print("Condition:", allinone)
humpty = " ".join([str(x) for x in allinone])
return eval(humpty)
# Building the parser
key = pp.Word(pp.alphanums + '_')('key')
op = pp.oneOf('> >= == != <= <')('op')
val = pp.Word(pp.nums + '-')('value')
joint = pp.oneOf("and or")
key.setParseAction(useKey)
val.setParseAction(toInt)
cond = pp.Group(key + op + val)('condition')
cond.addParseAction(checkCond)
logic = cond + pp.Optional(joint) + pp.Optional(cond)
# Tests
if __name__ == "__main__":
tests = [
("a == 5", False),
("b < 3", False),
("c > 1", True),
("d != 2", True),
("a >= 1", True),
("b <= 5", False),
("a <= 6 and b == 2", False),
("a <= 6 or b == 2", True)]
#("b > 2 and (a == 3 or d > 2 or c < 1)", True)]
for expr, res in tests:
print(expr)
out = logic.parseString(expr)
out = " ".join([str(x) for x in out])
out = bool(eval(out))
if bool(out) == bool(res):
print("PASS\n")
else: print("FAIL\n",
"Got:", bool(out),
"\nExpected:",bool(res), "\n")
经过大量的反复试验,我得到了预期的结果。但是请注意,最后一个测试已被注释掉;如果你取消注释并运行它,你会得到:
b > 2 and (a == 3 or d > 2 or c < 1)
Condition: [6, '>', 2]
Traceback (most recent call last):
File "testdat/pptutorial.py", line 191, in <module>
out = bool(eval(out))
File "<string>", line 1
True and
^
SyntaxError: unexpected EOF while parsing
我确定我错过了一些非常愚蠢的东西,但对于我的生活,我无法弄清楚这件作品。括号似乎使解析器认为这是新语句的开始。还有其他答案建议寻找空值,打印出单个令牌等,但我没有这样的运气。我的猜测是这与我在解析器中设置组的方式有关。我以前从未建造过,所以这对我来说绝对是未知领域!非常感谢您的帮助,如果我可以提供更多信息,请告诉我。
【问题讨论】:
-
如果这是一个迟钝的问题,请原谅我。您的语法是否在某处提供了带括号的表达式?
-
@BillBell 没有明确说明,但我的理解是 .setParseAction() 将括号读取为分组语句,除非另有说明。我发现但不能很好遵循的示例 (pyparsing.wikispaces.com/file/view/simpleBool.py/451074414/…) 正确处理了括号,但似乎只在其类中定义字符串表示 str 时才提及它们。我误会了吗?
-
显然你有一个非常直接的答案。
标签: python python-3.x parsing pyparsing