如何在 J 中定义一个动词,将不同的动词交替应用于列表中的每个原子?
想象一下,我在 J 中定义了以下名称:
m =: >: i. 2 4 5
看起来如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
我想创建一个 1 级的单子动词,应用于该列表列表中的每个列表。它将为列表中的每个替代项加倍 (+:
) 或加 1 (>:
)。如果我们将此动词应用于第一行,我们会得到2 3 6 5 10
。
获得与每个项目交替的布尔值列表相当容易,例如,0 1 $~{:$ m
为我们提供0 1 0 1 0
。我想,啊哈!我会使用类似 +:
`>: @.
的东西,后跟一些表达式,但我永远无法完全做到这一点让它发挥作用。
有什么建议吗?
更新
以下内容似乎可行,但也许 J 专业人士可以将其重构为更优雅的东西。
poop =: monad define (($ y) $ 0 1 $~{:$ y) ((]+:)`(]>:) @. [)"0 y )
Imagine I've defined the following name in J:
m =: >: i. 2 4 5
This looks like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
I want to create a monadic verb of rank 1 that applies to each list in this list of lists. It will double (+:
) or add 1 (>:
) to each alternate item in the list. If we were to apply this verb to the first row, we'd get 2 3 6 5 10
.
It's fairly easy to get a list of booleans which alternate with each item, e.g., 0 1 $~{:$ m
gives us 0 1 0 1 0
. I thought, aha! I'll use something like +:
`>: @.
followed by some expression, but I could never quite get it to work.
Any suggestions?
UPDATE
The following appears to work, but perhaps it can be refactored into something more elegant by a J pro.
poop =: monad define (($ y) $ 0 1 $~{:$ y) ((]+:)`(]>:) @. [)"0 y )
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我会使用排名为 1 的斜动词 (
/."1
) - 因此它依次适用于每个列表的连续元素。您可以将动名词传递到
/.
并且它按顺序应用它们,循环扩展。I would use the oblique verb, with rank 1 (
/."1
)- so it applies to successive elements of each list in turn.You can pass a gerund into
/.
and it applies them in order, extending cyclically.我花了很长时间看了它,我相信我知道为什么
,@
可以恢复论证的形状。带括号的短语的参数的形状是右侧传递给它的参数的形状,即使等级是由
"
共轭改变的(好吧,这就是跟踪所说的,我认为它是一个副词)。如果,
是一元词,那么它将是一个 ravel,并且基于 ravel That 的副词,结果将是一个向量或至少比输入的等级更低。如果你把连词拿出来,你会得到一个向量,所以我相信正在发生的是连词使
,
表现得像一个二元,
,它被称为。追加改变了它所追加的内容,但它仍然具有形状,因此它最终将中间向量更改回输入的形状。我可能错了,但是
$,"0@(+:
>:/.)"1 >: i.证明了我的情况。I spent a long time and I looked at it, and I believe that I know why
,@
works to recover the shape of the argument.The shape of the arguments to the parenthesized phrase is the shape of the argument passed to it on the right, even though the rank is altered by the
"
conjugate (well, that is what trace called it, I thought it was an adverb). If,
were monadic, it would be a ravel, and the result would be a vector or at least of a lower rank than the input, based on adverbs to ravel. That is what happens if you take the conjunction out - you get a vector.So what I believe is happening is that the conjunction is making
,
act like a dyadic,
which is called an append. The append alters what it is appending to what it is appending to. It is appending to nothing but that thing still has a shape, and so it ends up altering the intermediate vector back to the shape of the input.Now I'm probably wrong. But
$,"0@(+:
>:/.)"1 >: i. 2 4 5 -> 2 4 5 1 1` which I thought sort of proved my case.(,@(+:`>:/.)"1 a) 有效,但请注意 ((* 2 1 $~ $)@(+ 0 1 $~ $)"1 a) 也有效(并且在我的简短测试中,在大型阵列上大约快 20 倍)。
(,@(+:`>:/.)"1 a) works, but note that ((* 2 1 $~ $)@(+ 0 1 $~ $)"1 a) would also have worked (and is about 20 times faster, on large arrays, in my brief tests).
函数
+:`>:"0"1
这里使用常量动词
1:
和2:
是为了清楚地演示,但替换为你选择的动词。外部排名应用程序"1
表示将动词应用到每一行;内部排名应用程序 ("0
) 表示从其操作数开始在 0 单元(原子)之间交替是一个循环动名词。,@(+:`>:/."1)
的解释关于
,@(+:`>:/."1)
(来自别人的回答) 保留原始形状,这是因为u@v
被定义为(u@:v)"v
。在本例中v=.+:` >:/."1
,因此其等级为 1(1 1 1 的简写)。所以
,@v
⟶,@:v"v
⟶,@:v"1
⟶(,@:v)" 1
这意味着v
将单独应用于每一行,并且每个v
结果将分别由,
解析。在我们的例子中,v
在一行上的每次迭代都会生成一个 [5 1] 矩阵,因为f/.
会为每行的每个元素(通常是 .对角线,但行的各个元素)然后将该矩阵分解为一行;因此,[2 4 5 1 1] 形状中的第一个尾随 1 保持不变。从
[: $ ,"0@(+:`>:/.)"1
获得的结果是由于(…)"1
-结果 - 每个形状 [5 1] - 由2 4
构成框架,即相对于 1 单元格的框架(参见 https://code.jsoftware.com/wiki/Vocabulary/FramingFill#Argument_Frame_And_Result_Frame)。后者尾随 1 是由于,"0
将每个原子分解为单个向量。Function
+:`>:"0"1
Here the constant verbs
1:
and2:
are used for clear demonstration, but substitute with your verbs of choice. The outer rank application"1
says to apply our verb to each row; the inner rank application ("0
) says to alternate among 0-cells (atoms) since its operand is a cyclic gerund.Explanation of
,@(+:`>:/."1)
Regarding
,@(+:`>:/."1)
(from someone else's answer) preserving the original shape, this is becauseu@v
is defined as(u@:v)"v
. In this casev=.+:`>:/."1
, so its rank is 1 (a shorthand for 1 1 1).So
,@v
⟶,@:v"v
⟶,@:v"1
⟶(,@:v)"1
. This means thatv
will be applied separately on each row, and eachv
-result individually will be raveled by,
. In our case, each iteration ofv
on a row produces a [5 1] matrix sincef/.
produces a singleton list for each element of each row (generally the diagonals, but those of a row are its individual elements).,
then ravels that matrix into a row; thus, the shape remains unchanged.The first trailing 1 in the [2 4 5 1 1] shape that obtains from
[: $ ,"0@(+:`>:/.)"1
is due to the(…)"1
-results—each of shape [5 1]—being framed by2 4
, i.e., the frame with respect to the 1-cells (c.f. https://code.jsoftware.com/wiki/Vocabulary/FramingFill#Argument_Frame_And_Result_Frame). The latter trailing 1 is due to,"0
ravelling each atom into a singleton vector.