简体   繁体   English

如何过滤J中的列表?

[英]How to filter a list in J?

I'm currently learning the fascinating J programming language, but one thing I have not been able to figure out is how to filter a list. 我目前正在学习迷人的J编程语言,但有一点我无法弄清楚如何过滤列表。

Suppose I have the arbitrary list 3 2 2 7 7 2 9 and I want to remove the 2s but leave everything else unchanged, ie, my result would be 3 7 7 9 . 假设我有任意列表3 2 2 7 7 2 9并且我想删除2s但保留其他所有内容,即我的结果将是3 7 7 9 How on earth do I do this? 我怎么做到这一点?

The short answer 简短的回答

   2 (~: # ]) 3 2 2 7 7 2 9
3 7 7 9


The long answer 答案很长

I have the answer for you, but before you should get familiar with some details. 我有你的答案,但在你熟悉一些细节之前。 Here we go. 开始了。

Monads, dyads Monads,dyads

There are two types of verbs in J: monads and dyads . J中有两种类型的动词monaddyads The former accept only one parameter, the latter accept two parameters. 前者只接受一个参数,后者接受两个参数。

For example passing a sole argument to a monadic verb # , called tally , counts the number of elements in the list: 例如,将唯一参数传递给monadic动词# ,称为tally ,计算列表中元素的数量:

   # 3 2 2 7 7 2 9
7

A verb # , which accepts two arguments (left and right), is called copy , it is dyadic and is used to copy elements from the right list as many times as specified by the respective elements in the left list (there may be a sole element in the list also): 接受两个参数(左和右)的动词#被称为副本 ,它是二元的 ,用于从左侧列表中的相应元素指定的次数复制右侧列表中的元素(可能有一个列表中的元素也):

   0 0 0 3 0 0 0 # 3 2 2 7 7 2 9
7 7 7

Fork 叉子

There's a notion of fork in J, which is a series of 3 verbs applied to their arguments, dyadically or monadically. 在J中有一个fork概念,它是一系列3个动词,适用于他们的论证,可以是二元或一元的。

Here's the diagram of a kind of fork I used in the first snippet: 这是我在第一个片段中使用的一种分支图:

 x (F G H) y

      G
    /   \
   F     H
  / \   / \
 x   y x   y

It describes the order in which verbs are applied to their arguments. 它描述了动词应用于其参数的顺序。 Thus these applications occur: 因此这些应用发生:

   2 ~: 3 2 2 7 7 2 9
1 0 0 1 1 0 1

The ~: (not equal) is dyadic in this example and results in a list of boolean values which are true when an argument doesn't equal 2 . 在这个例子中, ~:不等于)是二元的 ,并且得到一个布尔值列表,当参数不等于2时,这些值为真。 This was the F application according to diagram. 这是根据图表的F应用程序。

The next application is H : 下一个应用是H

   2 ] 3 2 2 7 7 2 9
3 2 2 7 7 2 9

] ( identity ) can be a monad or a dyad , but it always returns the right argument passed to a verb (there's an opposite verb, [ which returns.. Yes, the left argument! :) ]identity )可以是monaddyad ,但它总是返回传递给动词的正确参数(有一个相反的动词, [返回..是的,左边的参数!:)

So far, so good. 到现在为止还挺好。 F and H after application returned these values accordingly: 应用程序后的FH相应地返回这些值:

1 0 0 1 1 0 1
3 2 2 7 7 2 9

The only step to perform is the G verb application. 要执行的唯一步骤是G动词应用程序。

As I noted earlier, the verb # , which is dyadic (accepts two arguments), allows us to duplicate the items from the right argument as many times as specified in the respective positions in the left argument. 正如我前面提到的,动词# ,它是二元的 (接受两个参数),允许我们从右参数复制项目的次数与左参数中相应位置的指定次数相同。 Hence: 因此:

   1 0 0 1 1 0 1 # 3 2 2 7 7 2 9
3 7 7 9

We've just got the list filtered out of 2 s. 我们刚刚从2秒过滤了列表。

Reference 参考

Slightly different kind of fork , hook and other primitves (including abovementioned ones) are described in these two documents: 这两个文件中描述了稍微不同的叉子钩子和其他原始物(包括上面提到的):

Other useful sources of information are the Jsoftware site with their wiki and a few mail list archives in internets. 其他有用的信息来源是Jsoftware网站 及其wiki以及互联网中的一些邮件列表存档。

Just to be sure it's clear, the direct way - to answer the original question - is this: 只是为了确定它是清楚的,直接的方式 - 回答原始问题 - 是这样的:

   3 2 2 7 7 2 9 -. 2

This returns 这回来了

3 7 7 9

The more elaborate method - generating the boolean and using it to compress the vector - is more APLish. 更精细的方法 - 生成布尔值并使用它来压缩向量 - 更加简洁。

To answer the other question in the very long post, to return the first element and the number of times it occurs, is simply this: 要在非常长的帖子中回答另一个问题,要返回第一个元素及其发生的次数,只需:

      ({. , {. +/ .= ]) 1 4 1 4 2 1 3 5
1 3

This is a fork using "{." 这是一个使用“{。”的分支。 to get the first item, "{. +/ . = ]" to add up the number of times the first item equals each element, and "," as the middle verb to concatenate these two parts. 得到第一项,“{。+ /。=]”加起来第一项等于每个元素的次数,“,”作为连接这两部分的中间动词。

Also: 也:

   2 ( -. ~ ]) 3 2 2 7 7 2 9
3 7 7 9

There are a million ways to do this - it bothers me, vaguely, that these these things don't evaluate strictly right to left, I'm an old APL programmer and I think of things as right to left even when they ain't. 有一百万种方法可以做到这一点 - 模糊地说,让我困扰的是,这些事情并没有严格从右到左进行评估,我是一个老的APL程序员,我认为即使不是。

If it were a thing that I was going to put into a program where I wanted to pull out some number and the number was a constant, I would do the following: 如果我要把它放到一个程序中,我想要提取一些数字而且数字是常数,我会做以下事情:

(#~ 2&~:)  1 3 2 4 2 5
1 3 4 5 

This is a hook sort of thing, I think. 我认为这是一种钩子。 The right half of the expression generates the truth vector regarding which are not 2, and then the octothorpe on the left has its arguments swapped so that the truth vector is the left argument to copy and the vector is the right argument. 表达式的右半部分生成的真值向量不是2,然后左边的octothorpe交换了参数,因此真值向量是要复制的左参数,向量是正确的参数。 I am not sure that a hook is faster or slower than a fork with an argument copy. 我不确定钩子比带有参数副本的fork更快或更慢。

  +/3<+/"1(=2&{"1)/:~S:_1{;/5 6$1+i.6

156 156

This above program answers the question, "For all possible combinations of Yatzee dice, how many have 4 or 5 matching numbers in one roll?" 上面的程序回答了这个问题:“对于Yatzee骰子的所有可能组合,一个卷中有多少个有4个或5个匹配数字?” It generates all the permutations, in boxes, sorts each box individually, unboxing them as a side effect, and extracts column 2, comparing the box against their own column 2, in the only successful fork or hook I've ever managed to write. 它生成所有排列,在框中,单独对每个框进行排序,将它们作为副作用取消装箱,并提取第2列,将框与它们自己的第2列进行比较,在我曾经设法编写的唯一成功的fork或hook中。 The theory is that if there is a number that appears in a list of 5, three or more times, if you sort the list the middle number will be the number that appears with the greatest frequency. 理论上说,如果列表中出现的数字为5次,3次或更多次,如果对列表进行排序,则中间数字将是出现频率最高的数字。 I have attempted a number of other hooks and/or forks and every one has failed because there is something I just do not get. 我尝试过其他一些钩子和/或叉子,每一个都失败了,因为有些东西我没有得到。 Anyway that truth table is reduced to a vector, and now we know exactly how many times each group of 5 dice matched the median number. 无论如何,真值表被简化为一个向量,现在我们确切地知道每组5个骰子与中位数相匹配的次数。 Finally, that number is compared to 3, and the number of successful compares (greater than 3, that is, 4 or 5) are counted. 最后,将该数字与3进行比较,并计算成功比较的数量(大于3,即4或5)。

This program answers the question, "For all possible 8 digit numbers made from the symbols 1 through 5, with repetition, how many are divisible by 4?" 该程序回答了这样一个问题,“对于所有可能的8位数字,从符号1到5,重复,有多少可以被4整除?”

I know that you need only determine how many within the first 25 are divisible by 4 and multiply, but the program runs more or less instantly. 我知道你只需要确定前25个中有多少可被4整除并相乘,但程序或多或少会立即运行。 At one point I had a much more complex version of this program that generated the numbers in base 5 so that individual digits were between 0 and 4, added 1 to the numbers thus generated, and then put them into base 10. That was something like 1+(8$5)#:i.5^8 +/0=4|,(8$10)#. 有一次,我有一个更复杂的程序版本,它生成了基数为5的数字,以便各个数字在0到4之间,为这样生成的数字加1,然后将它们放入基数10。这就像是1+(8$5)#:i.5^8 + / 0 = 4 |,(8 $ 10)#。 >{ ;/ 8 5$1+i.5 78125 As long as I have solely verb trains and selection, I don't have a problem. > {; / 8 5 $ 1 + i.5 78125只要我有动词训练和选择,我就没有问题。 When I start having to repeat my argument within the verb so that I'm forced to use forks and hooks I start to get lost. 当我开始不得不在动词中重复我的论点,以便我被迫使用叉子和钩子时,我开始迷路。

For example, here is something I can't get to work. 例如,这是我无法工作的东西。

((1&{~+/)*./\(=1&{))1 1 1 3 2 4 1

I always get Index Error. 我总是得到索引错误。

The point is to output two numbers, one that is the same as the first number in the list, the second which is the same as the number of times that number is repeated. 重点是输出两个数字,一个与列表中的第一个数字相同,第二个数字与重复数字的次数相同。

So this much works: 所以这很有效:

*./\(=1&{)1 1 1 3 2 4 1
1 1 1 0 0 0 0

I compare the first number against the rest of the list. 我将第一个数字与列表的其余部分进行比较。 Then I do an insertion of an and compression - and this gives me a 1 so long as I have an unbroken string of 1's, once it breaks the and fails and the zeros come forth. 然后我插入一个和压缩 - 这给了我一个1,只要我有一个完整的1的字符串,一旦它打破并失败并且零出现。

I thought that I could then add another set of parens, get the lead element from the list again, and somehow record those numbers, the eventual idea would be to have another stage where I apply the inverse of the vector to the original list, and then use $: to get back for a recursive application of the same verb. 我想我可以添加另一组parens,再次从列表中获取lead元素,并以某种方式记录这些数字,最终的想法是有另一个阶段,我将向量的逆应用于原始列表,并且然后使用$:来获取相同动词的递归应用。 Sort of like the quicksort example, which I thought I sort of understood, but I guess I don't. 有点像快速排序的例子,我认为我有点理解,但我想我没有。

But I can't even get close. 但我甚至无法接近。 I will ask this as a separate question so that people get proper credit for answering. 我会将此问题作为一个单独的问题,以便人们获得适当的回答。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM