我有以下(例如)数据
'a';'b';'c';'a';'b';'a'
┌─┬─┬─┬─┬─┬─┐
│a│b│c│a│b│a│
└─┴─┴─┴─┴─┴─┘
我想'a'
用一个数字替换 all 3
,然后'b'
用另一个数字4
,然后返回
┌─┬─┬─┬─┬─┬─┐
│3│4│c│3│4│3│
└─┴─┴─┴─┴─┴─┘
我怎样才能做到这一点?
感谢帮助。
我有以下(例如)数据
'a';'b';'c';'a';'b';'a'
┌─┬─┬─┬─┬─┬─┐
│a│b│c│a│b│a│
└─┴─┴─┴─┴─┴─┘
我想'a'
用一个数字替换 all 3
,然后'b'
用另一个数字4
,然后返回
┌─┬─┬─┬─┬─┬─┐
│3│4│c│3│4│3│
└─┴─┴─┴─┴─┴─┘
我怎样才能做到这一点?
感谢帮助。
如果那是一个字符串(如'abcaba'
),那么将有一个简单的解决方案rplc
:
'abcaba' rplc 'a';'3';'b';'4'
34c343
}
如果您需要像盒装数据一样拥有它(例如,如果 'a' 表示比字符或原子更复杂的东西),那么也许您可以使用amend}
:
L =: 'a';'b';'c';'a';'b';'a'
p =: I. (<'a') = L NB. positions of 'a' in L
0 3 5
(<'3') p } L NB. 'amend' "3" on those positions
将上述内容放入一个二元组:
f =: 4 :'({.x) (I.({:x) = y) } y' NB. amend '{.x' in positions where '{:x' = y
('3';'a') f L
┌─┬─┬─┬─┬─┬─┐
│3│b│c│3│b│3│
└─┴─┴─┴─┴─┴─┘
您可以在更复杂的设置中使用它:
]L =: (i.5);'abc';(i.3);'hello world';(<1;2)
┌─────────┬───┬─────┬───────────┬─────┐
│0 1 2 3 4│abc│0 1 2│hello world│┌─┬─┐│
│ │ │ │ ││1│2││
│ │ │ │ │└─┴─┘│
└─────────┴───┴─────┴───────────┴─────┘
((1;2);(i.3)) f L
┌─────────┬───┬─────┬───────────┬─────┐
│0 1 2 3 4│abc│┌─┬─┐│hello world│┌─┬─┐│
│ │ ││1│2││ ││1│2││
│ │ │└─┴─┘│ │└─┴─┘│
└─────────┴───┴─────┴───────────┴─────┘
顺便说一句,{.y
是第一项y
;{:y
是最后一项y
这是一个可以放入工具箱的小实用程序:
tr =: dyad def '(y i.~ ({." 1 x),y) { ({:" 1 x) , y'
] MAP =: _2 ]\ 'a';3; 'b';4
+-+-+
|a|3|
+-+-+
|b|4|
+-+-+
MAP tr 'a';'b';'c';'a';'b';'a'
+-+-+-+-+-+-+
|3|4|c|3|4|3|
+-+-+-+-+-+-+
该实用程序tr
是一个带有两个参数(一个二元组)的动词:右边的参数是目标,左边的参数是映射表。该表必须有两列,每一行代表一个映射。为了只进行一次替换,可以接受包含两个项目的向量(即,一维列表而不是二维表,只要列表有两个项目长)。
请注意,该表必须与目标具有相同的数据类型(因此,如果要替换框,则它必须是框表;如果是字符,则必须是字符表;数字表示数字等)。
而且,由于我们在做同类映射,映射表的单元格必须与目标的项目具有相同的形状,因此它不适合字符串替换等可能需要变形的任务。例如,('pony';'horse') tr 'I want a pony for christmas'
不会工作(但有趣的是,'pony horse' tr&.;: 'I want a pony for christmas'
会因为我不会进入的原因)。
您的问题没有一个标准答案。也就是说,有一个非常常见的习语来进行翻译(在tr
, 或映射 1:1 的意义上):
FROM =: ;: 'cat dog bird'
TO =: ;: 'tiger wolf pterodactyl'
input=: ;: 'cat bird dog bird bird cat'
(FROM i. input) { TO
+-----+-----------+----+-----------+-----------+-----+
|tiger|pterodactyl|wolf|pterodactyl|pterodactyl|tiger|
+-----+-----------+----+-----------+-----------+-----+
为了打破这一点,原语i.
是查找功能,原语{
是选择功能(助记符:为您提供您正在寻找的元素 i.
的* i *索引)。
但是上面的简单公式仅适用于您想要替换输入中的所有内容,并且FROM
保证是全部的(即输入的项目被限制为 中的任何内容FROM
)。
这些约束使简单的公式适用于字符串的大小写转换等任务,您想要替换所有字母,并且我们预先知道字母的总范围(即字母表是有限的)。
但是如果我们没有一个有限的宇宙会发生什么呢?我们应该如何处理无法识别的物品?好吧,我们想要的任何东西。这种对灵活性的需求是 J 中没有单一翻译功能的原因:相反,该语言为您提供了工具来制定特定于您的需求的解决方案。
例如,对上述模式的一个非常常见的扩展是默认替换的概念(对于无法识别的项目)。而且,因为i.
定义为返回1+#input
查找中未找到的项目,所以扩展非常简单:我们只需将替换列表扩展一项,即添加默认值!
DEFAULT =: <'yeti'
input=: ;: 'cat bird dog horse bird monkey cat iguana'
(FROM i. input) { TO,DEFAULT
+-----+-----------+----+----+-----------+----+-----+----+
|tiger|pterodactyl|wolf|yeti|pterodactyl|yeti|tiger|yeti|
+-----+-----------+----+----+-----------+----+-----+----+
当然,从不可逆转的意义上说,这是破坏性的:它不会留下有关输入的信息。有时,就像您的问题一样,如果您不知道如何替换某些东西,最好不要管它。
同样,这种扩展非常简单,而且,一旦您看到它,就很明显:您通过附加输入来扩展查找表。这样,您就可以保证找到输入的所有项目。替换也同样简单:通过附加输入来扩展替换列表。因此,您最终会用自己替换所有未知项目。
( (FROM,input) i. input) { TO,input
+-----+-----------+----+-----+-----------+------+-----+------+
|tiger|pterodactyl|wolf|horse|pterodactyl|monkey|tiger|iguana|
+-----+-----------+----+-----+-----------+------+-----+------+
这就是所体现的策略tr
。
顺便说一句,在编写类似 的实用程序时tr
,J 程序员通常会考虑 N 维情况,因为那是语言的精神。就目前而言,tr
需要一个二维映射表(并且,意外地,将接受两个项目的一维列表,这很方便)。但是可能有一天我们想要替换立方体内的平面,或超立方体内的立方体等(在商业智能应用程序中很常见)。如果出现这些情况,我们可能希望扩展该实用程序以涵盖这些情况。
但是怎么做?好吧,我们知道映射表必须至少有两个维度:一个保存多个同时替换,另一个保存替换规则(即每个替换一个“行”和两个“列”来标识一个项目及其替换) . 这里的关键是这就是我们所需要的。概括tr
地说,我们只需要说我们不关心这些维度之下的内容。它可以是 Nx2 单个字符表,或 Nx2 固定长度字符串表,或用于某些线性代数目的的 Nx2 矩阵表,或者......谁在乎?不是我们的问题。我们只关心框架,而不关心内容。
所以让我们这么说,在tr
:
NB. Original
tr =: dyad def '(y i.~ ({." 1 x),y) { ({:" 1 x) , y'
NB. New, laissez-faire definition
tr =: dyad def '(y i.~ ({."_1 x),y) { ({:"_1 x) , y'
如您所见,这是一项繁重的变化;)。不太流畅:等级运算符"
可以采用正或负参数。一个肯定的参数让动词处理其输入的内容,而一个否定的参数让动词处理其输入的框架。这里,"1
(正)适用{.
于 的行x
,而"_1
(负)适用于 的“行” x
,其中引号中的“行”仅表示沿第一个维度的项目,即使它们恰好是 37维超矩形。谁在乎?
好吧,一个人在乎。让最懒的tr
程序员写('dog';'cat') tr ;: 'a dog makes the best pet'
而不是(,:'dog';'cat') tr ;: 'a dog makes the best pet'
. 也就是说,原始tr
(完全意外)允许将简单列表作为映射表,这当然不是 Nx2 表,即使在抽象的虚拟意义上也是如此(因为它至少没有两个维度)。也许我们想保留这种便利。如果是这样,我们必须代表用户推广退化论点:
tr =: dyad define
x=.,:^:(1=#@$) x
(y i.~ ({."_1 x),y) { ({:"_1 x) , y
)
毕竟,懒惰是程序员的主要美德。
这是我能想到的完成您所要求的最简单的方法:
(3;3;3;4;4) 0 3 5 1 4} 'a';'b';'c';'a';'b';'a'
┌─┬─┬─┬─┬─┬─┐
│3│4│c│3│4│3│
└─┴─┴─┴─┴─┴─┘
这是另一种方法
(<3) 0 3 5} (<4) 1 4} 'a';'b';'c';'a';'b';'a'
┌─┬─┬─┬─┬─┬─┐
│3│4│c│3│4│3│
└─┴─┴─┴─┴─┴─┘
假设地说,您可能想要概括这种表达,或者您可能想要一个替代方案。我认为这里的其他海报已经指出了这样做的方法。. 但有时只看最简单的形式会很有趣吗?
顺便说一句,这是我获得上述索引的方式(删除了一些但不是所有不相关的内容):
I. (<'a') = 'a';'b';'c';'a';'b';'a'
0 3 5
('a') =S:0 'a';'b';'c';'a';'b';'a'
1 0 0 1 0 1
('a') -:S:0 'a';'b';'c';'a';'b';'a'
1 0 0 1 0 1
I.('a') -:S:0 'a';'b';'c';'a';'b';'a'
0 3 5
I.('b') -:S:0 'a';'b';'c';'a';'b';'a'
1 4