使用搜索运算符仅在存在匹配项时查找

Using Search operator to find out only if there is a match

在 Dyalog APL 中使用运算符 ⎕S 时,我只对是否匹配感兴趣,因此表达式

('foo' ⎕S F) 'foo' 'bar' 'foofoo'

应该评估为

.→----.
|1 0 1|
'~----'

什么函数(或字符串)F 会实现这个?

编辑:这个例子只是为了说明这一点。在实践中,正则表达式可能要复杂得多。

免责声明

⎕S 是一个具有许多功能的强大野兽 - 但我不确定它是否适合执行检查是否存在匹配这样简单的工作。但也许您试图简化一个复杂的问题 - 或者也许我对 ⎕S 的理解不够透彻。 所以我想展示我将如何解决给定的问题,然后看看潜在的 ⎕S-approaches.

查找

Find returns 一个布尔向量,在搜索字符串的起始位置。 所以我会在每个向量中找到一个,然后是 ∨/(or-reduce) 以确定是否存在匹配项:

      ∨/¨'foo'∘⍷¨'foo' 'bar' 'foofoo' 
1 0 1

⎕S

使用 ⎕S,您甚至可以在嵌套参数上使用正则表达式进行搜索。所以我们需要使用每个运算符 ¨ 对 3 个向量中的每一个应用 ⎕S f

   {('foo'⎕S f)⍵}¨'foo' 'bar' 'foofoo' 

那么它可以做很多事情return:

  • 任何匹配的长度:使用f=转换代码1,它将return匹配字符串的长度.由于我们有一个固定的模式,它可以是任意数量的 3(零到 n)。在你的例子中:
    {('foo'⎕S 1 )⍵}¨'foo' 'bar' 'foofoo' 
    
┌─┬┬───┐
│3││3 3│
└─┴┴───┘

最后,检查我们是否有任何 3s,我们得到了想要的结果:

      3∊¨{('foo'⎕S 1 )⍵}¨'foo' 'bar' 'foofoo' 
1 0 1
  • 匹配字符串本身。使用转换模式 &,它将 return 匹配的字符串:
    {('foo'⎕S '&' )⍵}¨'foo' 'bar' 'foofoo' 
┌─────┬┬─────────┐
│┌───┐││┌───┬───┐│
││foo││││foo│foo││
│└───┘││└───┴───┘│
└─────┴┴─────────┘

检查是否有匹配,我们就完成了:

     0<≢¨{('foo'⎕S '&' )⍵}¨'foo' 'bar' 'foofoo' 
1 0 1
  • 最后,也用 转换函数 覆盖那个。为找到的每个匹配项调用 TF 并传递一个名称空间,其中包含描述匹配项的各种字段。 (help 记录了各种可能性,我将使用 .Lengths,它在前面的示例中给出了相同的转换代码 1
      {('foo'⎕S {⍵.Lengths} )⍵}¨'foo' 'bar' 'foofoo' 
┌───┬┬─────┐
│┌─┐││┌─┬─┐│
││3││││3│3││
│└─┘││└─┴─┘│
└───┴┴─────┘
      0<≢¨{('foo'⎕S {⍵.Lengths} )⍵}¨'foo' 'bar' 'foofoo' 
1 0 1

实际上,我们根本不需要 Lengths - 我们可以检查它是否收到任何呼叫:

      ∨/¨{('foo'⎕S {0<≢⍵} )⍵}¨'foo' 'bar' 'foofoo' 
1 0 1

结束

我希望这能给你一些想法:)

      (≢'foo'⎕S 3⍠'ML'1)¨'foo' 'bar' 'foofoo'
1 0 1

这里发生了什么?

⎕S 3 returns 从 0 开始匹配的模式(所以如果你只有一个模式,它总是 0)

⍠'ML'1 将匹配限制设置为 1,因此 ⎕S 不会在找到第一个匹配项后继续搜索元素。这确保了每个结果最多有一个元素,并且还通过在我们已经足够了解时不进一步搜索来提高性能——一个匹配项。

( 是必要的,因为我们必须分别搜索每个字符向量。如果我们只是想知道该模式是否出现在文档中的任何地方,我们不需要这个。

计算每个结果中模式索引的数量。由于我们设置了匹配限制,每个结果将是 1 元素向量(如果找到)或 0 元素向量(如果未找到),因此我们的总体结果将是我们想要的布尔向量。

Try it online!


值得注意的是⎕S会分析你的搜索模式,如果搜索不需要正则表达式,它会使用更快的搜索算法,所以你可以依靠⎕S而不担心需要使用 来获得简单模式的最佳性能。