对于具有命名列的表中的数据的通用操作,我建议您参考我的this 解决方案,以解决类似的问题。对于任何特定情况,手动为Select 编写函数可能更容易。但是,对于许多列和许多不同的查询,弄乱索引的机会很高。这是来自上述帖子的修改后的解决方案,它提供了更友好的语法:
Clear[getIds];
getIds[table : {colNames_List, rows__List}] := {rows}[[All, 1]];
ClearAll[select, where];
SetAttributes[where, HoldAll];
select[cnames_List, from[table : {colNames_List, rows__List}], where[condition_]] :=
With[{colRules = Dispatch[ Thread[colNames -> Thread[Slot[Range[Length[colNames]]]]]],
indexRules = Dispatch[Thread[colNames -> Range[Length[colNames]]]]},
With[{selF = Apply[Function, Hold[condition] /. colRules]},
Select[{rows}, selF @@ # &][[All, cnames /. indexRules]]]];
这里发生的是Select 中使用的函数是根据您的规范自动生成的。例如(使用@Yoda 的例子):
rows = Array[#1 #2 &, {5, 15}];
我们需要定义列名(必须是不带值的字符串或符号):
In[425]:=
colnames = "c" <> ToString[#] & /@ Range[15]
Out[425]= {"c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", "c12",
"c13", "c14", "c15"}
(在实践中,通常名称当然更具描述性)。这是表格:
table = Prepend[rows, colnames];
这是您需要的选择语句(我选择了x = 4 和y=2):
select[{"c1", "c2", "c3", "c6", "c7", "c8", "c9", "c15"}, from[table],
where["c2" == 4 && "c8" != 2]]
{{2, 4, 6, 12, 14, 16, 18, 30}}
现在,对于单个查询,这可能看起来是一种复杂的方法。但是你可以做很多不同的查询,比如
In[468]:= select[{"c1", "c2", "c3"}, from[table], where[EvenQ["c2"] && "c10" > 10]]
Out[468]= {{2, 4, 6}, {3, 6, 9}, {4, 8, 12}, {5, 10, 15}}
和类似的。
当然,如果您的数据中存在特定的相关性,您可能会找到一种更快的特定专用算法。上面的函数可以通过多种方式进行扩展,以简化常见查询(包括“all”等),或自动编译生成的纯函数(如果可能)。
编辑
在哲学上,我相信许多 Mathematica 用户(包括我自己)发现自己不时地一次又一次地编写类似的代码。 Mathematica 具有简洁的语法这一事实使得它通常很容易为任何特定情况编写。但是,只要一个人在某个特定领域工作(例如,表中的数据操作),对于许多操作来说,重复自己的成本就会很高。我的示例在一个非常简单的设置中说明了一种可能的出路 - 创建一种特定于域的语言 (DSL)。为此,通常需要为它定义一个语法/语法,并从它编写一个编译器到 Mathematica(以自动生成 Mathematica 代码)。现在,上面的例子是这个想法的一个非常原始的实现,但我的观点是,Mathematica 通常非常适合 DSL 创建,我认为这是一种非常强大的技术。