APL - Как мне найти самое длинное слово в строковом векторе?

Я хочу найти самое длинное слово в строковом векторе. Используя APL, я знаю, что функция shape будет возвращать длину строки, например

⍴ 'string' ⍝ returns 6

Функция Reduce позволяет мне отображать диадические функции вдоль вектора, но поскольку форма является монадической, это не сработает. Как я могу отобразить функцию формы в этом случае? Например:

Если вектор определен как:

lst ← 'this is a string'

Я хочу сделать это:

⍴'this' ⍴'is' ⍴'a' ⍴'string'

2 ответа

Решение

"Типичный" подход заключается в том, чтобы рассматривать ее как сегментированную (или: разделенную) строку и добавлять к ней префикс с разделителем (пробел) и передавать его в dfn для дальнейшего анализа:

{}' ',lst

Затем fn ищет разделитель и использует его для построения векторов слов:

      {(⍵=' ')⊂⍵}' ',lst
┌─────┬───┬──┬───────┐
│ this│ is│ a│ string│
└─────┴───┴──┴───────┘

Давайте удалим пробелы:

      {1↓¨(⍵=' ')⊂⍵}' ',lst
┌────┬──┬─┬──────┐
│this│is│a│string│
└────┴──┴─┴──────┘

И тогда вам "просто" нужно вычислить длину каждого вектора:

{1↓¨(⍵=' ')⊂⍵}' ',lst

Это прямая реализация вашего запроса. Однако, если вас не интересуют сами подстроки, а только длина "непустых сегментов", более подходящим решением "APLy" может быть работа с логическими значениями (обычно наиболее эффективными):

      lst=' '
0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0

Итак, позиции сепараторов - где они встречаются?

      ⍸lst=' '
5 8 10

Но нам также нужен завершающий пробел - иначе мы пропускаем конец текста:

      ⍸' '=lst,' '
5 8 10 17

Так эти (minus the positions of the preceeding blank) следует указать длину отрезков:

      {¯1+⍵-0,¯1↓⍵}⍸' '=lst,' '
4 2 1 6

Это все еще несколько наивно и может быть выражено более продвинутым способом - я оставляю это как "упражнение для читателя";-)

Хотя MBaas уже подробно ответил, я подумал, что было бы интересно изучить идиоматический "поезд" Дьялога. ≠⊆⊢ получено из комментария Пола Мансура. Он формирует двоичную функцию, которая разбивает свой правый аргумент на вхождения левого аргумента:

      Split ← ≠⊆⊢
      ' ' Split 'this is a string'
┌────┬──┬─┬──────┐
│this│is│a│string│
└────┴──┴─┴──────┘

Вы можете расширить эту функцию, чтобы выполнить всю работу:

      SegmentLengths ← ≢¨Split
      ' ' SegmentLengths 'this is a string'
4 2 1 6

Или даже объединить определения за один раз:

      SegmentLengths ← ≢¨≠⊆⊢
      ' ' SegmentLengths 'this is a string'
4 2 1 6

Если вы привыкли к идиоматическому выражению ≠⊆⊢ тогда оно может на самом деле читаться яснее, чем любое подходящее имя, которое вы можете дать для функции, так что вы можете просто использовать выражение in-line:

      ' ' (≢¨≠⊆⊢) 'this is a string'
4 2 1 6

Чтобы найти самое длинное слово в строке, которую я бы использовал, в NARS APL функция

f←{v/⍨k=⌈/k←≢¨v←(⍵≠' ')⊂⍵}

пример для использования

  f  'this is a string thesam'
string thesam 

объяснение

{v/⍨k=⌈/k←≢¨v←(⍵≠' ')⊂⍵}
            v←(⍵≠' ')⊂⍵  split the string where are the spaces and assign result to v
        k←≢¨v             to each element of v find the lenght, the result will be a vector
                          that has same lenght of v saved in k
      ⌈/k                 this find max in k
    k=                    and this for each element of k return 0 if it is not max, 1 if it is max
 v/⍨                      this return the element of v that are max
Другие вопросы по тегам