我的想法是创建一种用于表格分析的受限语言形式。问题是,是否已经有类似下面这样的东西,或者是否有更好的想法去做。关键的要求是用户必须能够使用裸脚本文件,而无需生成完整的Python程序。脚本语言的OTOH元素是在运行时编译的,并且应该提供一种可能来描述复杂的条件和计算(主要是算术和字符串操作)。用这种语言编写程序的声明性方法(见下文)禁止直接使用Python语法作为语言的载体(参见@PART函数的含义)——至少我认为是这样。
有没有一种更好/更聪明/更优雅的方法来实现我的目标,而不是像我下面这样用Python和笨拙的自定义语法混合编程?在
下面我试图通过一个例子来阐明我的想法。输入表由另一个程序部件生成,在脚本解释开始时如下所示:# First,Last,Department,Hourly Wage
[ ('Greg','Foo','HR',100),
('Judy','Bar','EE',51),
('Jake','Baz','HR',75),
('Lila','Bax','HR',49),
('Norm','Fob','EE',49) ]
文件本身就在脚本后面。这将是生产系统中自己的文件。程序代码目前是作为一个Python字符串的数组来编写的,在最终版本中甚至可能没有。在
^{pr2}$
我会一步一步地解释剧本应该做什么:"@SORT(2,-3)"
在第2列(升序)之后,然后在第3列(降序)之后对表进行排序。我们得到了[ ('Judy','Bar','EE',51),
('Norm','Fob','EE',49),
('Greg','Foo','HR',100),
('Jake','Baz','HR',75),
('Lila','Bax','HR',49),
]
"@SET({max},@MAX({3}))"
取第3列的最大值,并将其放入动态局部变量max中"@PART({2}!={^2} or {3}
有点复杂。@PART对当前表进行分区
通过计算每一行的给定表达式并在行前面剪切(如果为真),可以将其分为多个子表。
这里我们要在部门边界处(第2列)。{^2}是向上引用,表示第2列中的元素
从上一行开始。这种语法是必要的,因为我认为在更复杂的条件下对表进行分区的能力
“row differences from previous row in X”非常重要(假设您要将表划分为10k收入类)
所以我需要一个(受限的)Python表达式在PART参数中的表达能力。这也意味着
因为没有前置函数,所以无法为第一行计算表达式,因此
只会简单地回顾一下。
在此函数之后,我们有以下表格:[ ('Judy','Bar','EE',51) ] # Department EE
[ ('Norm','Fob','EE',49) ] # Norm Fob is in the same department but earns less than half of the maximum
[ ('Greg','Foo','HR',100), # New department HR
('Jake','Baz','HR',75) ]
[ ('Lila','Bax','HR',49) ] # HR dept. but less than half of the best earner
从现在开始,脚本中的函数将分别在每个子表上工作。部分功能或多或少
在所有生成的子表上启动循环,并对以下每个函数(包括更多部分)执行
孤立的子表。在"@SET({dep},@FIRST({2}))",
"@PRINT({dep},float(@SUM({3}))/@CNT({3}))"
@FIRST({2})只接受第一行第2列的值。@SUM({3})取整列3的和
并且@CNT({3})正在计算列3不等于None的行数。
我大致描述了函数的结果:[ ('Judy','Bar','EE',51) ]
"@SET({dep},@FIRST({2}))" --> {dep} = "EE"
"@PRINT({dep},float(@SUM({3}))/@CNT({3}))" --> output "EE 51"
[ ('Norm','Fob','EE',49) ]
"@SET({dep},@FIRST({2}))", --> {dep} = "EE"
"@PRINT({dep},float(@SUM({3}))/@CNT({3}))" --> output "EE 49"
[ ('Greg','Foo','HR',100),
('Jake','Baz','HR',75) ]
"@SET({dep},@FIRST({2}))", --> {dep} = "HR"
"@PRINT({dep},float(@SUM({3}))/@CNT({3}))" --> output "HR 87.5"
[ ('Lila','Bax','HR',49) ]
"@SET({dep},@FIRST({2}))", --> {dep} = "HR"
"@PRINT({dep},float(@SUM({3}))/@CNT({3}))" --> output "HR 49"
我应该补充一点,我更喜欢保持解决方案的小型化,即不使用非标准的Python包,比如pyparsing等