J中的连锁动词

MPe*_*ier 6 j

假设包含各种类型的盒装矩阵:

matrix =: ('abc';'defgh';23),:('foo';'bar';45)
matrix
Run Code Online (Sandbox Code Playgroud)
+---+-----+--+
|abc|defgh|23|
+---+-----+--+
|foo|bar  |45|
+---+-----+--+

列描述符:

columnTypes =: 'string';'string';'num'
Run Code Online (Sandbox Code Playgroud)

我想根据类型按列在这个矩阵上应用动词.我将使用动词DoString和DoNum:

chain =: (('string';'num') i. columnTypes) { DoString`DoNum
Run Code Online (Sandbox Code Playgroud)

编辑:列描述符很重要,决定使用哪个动词是基于它们,而不是基于类型本身.实际上,我可以有几种类型的字符串,数字,甚至日期(在J中都是数字).

我如何申请chain每一行matrix?动词本身可以处理传递的值是否为盒装,这很好.另外,我宁愿避免转置矩阵(|:),因为它可能非常大.

Dan*_*ron 5

这样做的标准方法是:

  1. 将行(单元)定向结构转换为面向列的结构

  2. 将正确的动词应用于每列(仅一次)

步骤(1)很容易.步骤(2)也很容易,但不是那么明显.有一个小技巧有帮助.

诀窍是知道许多原始运算符接受一个动名词作为左参数并产生一个循环在动名词上的函数,依次应用每个动词.IMO,这个类别中最有用的运营商是;. .这是使用它的示例实现:

步骤(0),输入:

   matrix      =:  ('abc';'defgh';23),:('foo';'bar';45)

   columnTypes =:  'string';'string';'num'

   DoString    =:  toupper
   DoNum       =:  0&j.

   matrix
+---+-----+--+
|abc|defgh|23|
+---+-----+--+
|foo|bar  |45|
+---+-----+--+
Run Code Online (Sandbox Code Playgroud)

步骤(1),校准数据:

   columnify   =:  <@:>"1@:|: :. rowify =: <"_1&>
   columnify matrix
+---+-----+-----+
|abc|defgh|23 45|
|foo|bar  |     |
+---+-----+-----+
Run Code Online (Sandbox Code Playgroud)

请注意,列化提供了一个反向,它将重新"划分"数据,但您不应该这样做:见下文.

步骤(2),使用以下动词循环功能将正确的动词应用于每一列(恰好一次);.:

   homogenize  =:  ({. foo&.>@:{.`'') [^:('foo'-:])L:0~ ]
   chain       =:  DoString`DoNum`] homogenize@{~  ('string';'num')&i.  
Run Code Online (Sandbox Code Playgroud)

请注意,未知列类型的默认转换是标识函数].

动词homogenize规范化每个列处理器的输入和输出(即抽象出预处理和后处理,以便用户只需提供转换的动态"核心").动词chain将列类型列表作为输入,并派生适合使用左手参数;.(或类似运算符)的动名词.

从而:

   1 (chain columnTypes);.1  columnify matrix
+---+-----+---------+
|ABC|DEFGH|0j23 0j45|
|FOO|BAR  |         |
+---+-----+---------+
Run Code Online (Sandbox Code Playgroud)

或者,如果您确实必须有一个盒装单元格的NxM表,请应用"下"列下的剪切:

   1 (chain columnTypes);.1&.columnify matrix
+-----+-----+
|ABC  |FOO  |
+-----+-----+
|DEFGH|BAR  |
+-----+-----+
|0j23 |0j45 |
+-----+-----+
Run Code Online (Sandbox Code Playgroud)

但请注意,出于性能和符号原因,在J上下文中,将表保持为同类列的列表更为合适.

当处理数组"in toto"时,J效果最佳; 根据经验,您应该让原始或用户定义的名称在每个应用程序中查看尽可能多的数据.这是"columificaton"方法的主要好处:如果将数据存储为同类列的列表,则以后操作会更快更容易.

但是,如果您的用例确实要求您将数据保存为盒装单元格的NxM表,那么将数据转换为正常形式的列表是一种昂贵的无操作.在这种情况下,你应该坚持原来的解决方案,

   1 chain\"1 matrix
Run Code Online (Sandbox Code Playgroud)

(因为你问)实际上与;.方法相同的前提.特别是,\是接受动名词参数的另一个原始运算符,并且连续地应用每个动词(即,循环地对每个新的数据窗口应用).

实际上,什么1 chain\"1 matrix是将矩阵分解为rows("1),并且对于每一行,它创建一个1宽的移动窗口,(1 f\ matrix),以圆柱方式应用chain每个1宽窗口的动词(即f每1个更改一次)矩阵每行的全数据窗口).

由于一行(一级-1矢量)的移动1窗口是行的原子,按顺序,并且动词的chain顺序是相同的,所以实际上你将这些动词应用于矩阵,一个.原子.在.一个.时间.

简而言之: 1 chain\"1 matrix类似于foo"0 matrix,除了每个原子的foo变化.并且应该避免出于同样的原因foo"0 matrix应该避免一般:因为应用小等级的函数会对J的粒度起作用,从而导致性能损失.

通常,最好在可能的情况下使用更高级别的应用函数,在这种情况下,需要将转换(和维护)转换matrix为列正态形式.

换句话说,在这里,;."1因为\"0.如果您发现整个columnify/ homogenize东西过于冗长或过于庞大(1 chain\"1 matrix与之相比),您可以导入[1]中提供的脚本,该脚本将这些定义打包为可重用的实用程序,并附带扩展名.有关示例和说明,请参阅该页面.

[1]相关实用程序脚本:http:
//www.jsoftware.com/jwiki/DanBron/Snippets/DOOG


MPe*_*ier 0

通过实验,我让它做我想做的事:

1 chain\"1 matrix
Run Code Online (Sandbox Code Playgroud)

现在要了解它...