Find

Find (โท) searches for occurrences of an array ๐•จ within ๐•ฉ. The result contains a boolean for each possible location, which is 1 if ๐•จ was found there and 0 if not.

โ†—๏ธ
    "xx" โท "xxbdxxxcx"
โŸจ 1 0 0 0 1 1 0 0 โŸฉ

More precisely, ๐•จ needs to match a contiguous selection from ๐•ฉ, which for strings means a substring. These subarrays of ๐•ฉ are also exactly the cells in the result of Windows. So we can use Windows to see all the arrays ๐•จ will be compared against.

โ†—๏ธ
    2 โ†• "xxbdxxxcx"
โ”Œโ”€    
โ•ต"xx  
  xb  
  bd  
  dx  
  xx  
  xx  
  xc  
  cx" 
     โ”˜

    "xx"โŠธโ‰กห˜ 2 โ†• "xxbdxxxcx"
โŸจ 1 0 0 0 1 1 0 0 โŸฉ

Like Windows, the result usually doesn't have the same dimensions as ๐•ฉ. This is easier to see when ๐•จ is longer. It differs from APL's version, which includes trailing 0s in order to maintain the same length. Bringing the size up to that of ๐•ฉ is easy enough with Take (โ†‘), while shortening a padded result would be harder.

โ†—๏ธ
    "string" โท "substring"
โŸจ 0 0 0 1 โŸฉ

    "string" (โ‰ขโˆ˜โŠขโ†‘โท) "substring"  # APL style
โŸจ 0 0 0 1 0 0 0 0 0 โŸฉ

If ๐•จ is larger than ๐•ฉ, the result is empty, and there's no error even in cases where Windows would fail. One place this tends to come up is when applying First (โŠ‘) to the result: โŠ‘โท tests whether ๐•จ appears in ๐•ฉ at the first position, that is, whether it's a prefix of ๐•ฉ. If ๐•จ is longer than ๐•ฉ it shouldn't be a prefix. First will fail but using a fold 0โŠฃยดโท instead gives a 0 in this case.

โ†—๏ธ
    "loooooong" โท "short"
โŸจโŸฉ

    9 โ†• "short"
Error: โ†•: Window length ๐•จ must be at most axis length plus one

    0 โŠฃยด "loooooong" โท "short"
0

Adding a Deshape gives 0โŠฃยดโฅŠโˆ˜โท, which works with the high-rank case discussed below. It tests whether ๐•จ is a multi-dimensional prefix starting at the lowest-index corner of ๐•ฉ.

Higher ranks

If ๐•จ and ๐•ฉ are two-dimensional then Find does a two-dimensional search. The cells used are also found in ๐•จโ‰ขโŠธโ†•๐•ฉ. For example, the bottom-right corner of ๐•ฉ below matches ๐•จ, so there's a 1 in the bottom-right corner of the result.

โ†—๏ธ
    โŠข a โ† 7 (4|โ‹†หœ)โŒœโ—‹โ†• 9   # Array with patterns
โ”Œโ”€                   
โ•ต 1 1 1 1 1 1 1 1 1  
  0 1 2 3 0 1 2 3 0  
  0 1 0 1 0 1 0 1 0  
  0 1 0 3 0 1 0 3 0  
  0 1 0 1 0 1 0 1 0  
  0 1 0 3 0 1 0 3 0  
  0 1 0 1 0 1 0 1 0  
                    โ”˜

    (0โ€ฟ3โ€ฟ0โ‰0โ€ฟ1โ€ฟ0) โท a
โ”Œโ”€               
โ•ต 0 0 0 0 0 0 0  
  0 0 0 0 0 0 0  
  0 0 0 0 0 0 0  
  0 0 1 0 0 0 1  
  0 0 0 0 0 0 0  
  0 0 1 0 0 0 1  
                โ”˜

It's also allowed for ๐•จ to have a smaller rank than ๐•ฉ; the axes of ๐•จ then correspond to trailing axes of ๐•ฉ, so that leading axes of ๐•ฉ are mapped over. This is a minor violation of the leading axis principle, which would match axes of ๐•จ to leading axes of ๐•ฉ in order to make a function that's useful with the Rank operator, but such a function would be quite strange and hardly ever useful.

โ†—๏ธ
    0โ€ฟ1โ€ฟ0โ€ฟ1 โท a
โ”Œโ”€             
โ•ต 0 0 0 0 0 0  
  0 0 0 0 0 0  
  1 0 1 0 1 0  
  0 0 0 0 0 0  
  1 0 1 0 1 0  
  0 0 0 0 0 0  
  1 0 1 0 1 0  
              โ”˜