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