Я хочу найти самое длинное слово в векторе строки. Используя APL, я знаю, что функция формы вернет длину строки, например.
⍴ 'string' ⍝ returns 6
Функция редукции позволяет отображать диадические функции вдоль вектора, но, поскольку форма является монадической, это не сработает. Как я могу отобразить функцию формы в этом случае? Например:
Если вектор определяется как:
lst ← 'this is a string'
Я хочу сделать это:
⍴'this' ⍴'is' ⍴'a' ⍴'string'
«Типичным» подходом было бы рассматривать ее как сегментированную (или: разделенную) строку с префиксом разделителя (пустой) и передавать ее в 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
Это все еще несколько наивно и может быть выражено более продвинуто - я оставляю это как "упражнение для читателя" ;-)
Спасибо - не подумал об использовании логического метода, который вы описали. Элегантный!
Да, логические значения так полезны в APL — их невозможно переоценить!
Или просто ≢¨(' '≠lst)⊆lst
Да! Но это "продвинутый" ;-)
Хорошо. Только что проверил, как работает пример @Paul Mansour; (i) создать вложенный список отдельных слов; (ii) разделить предложение на слова, используя двоичный вывод (' '≠lst), затем применить функцию подсчета к каждому слову. Спасибо! Это тоже работает: ⍴ ¨(' '≠lst)⊆lst
Конечно. Важно отметить, что tally всегда возвращает простой скаляр, тогда как shape (rho) возвращает вектор. Таким образом, tally, примененный к каждому, возвращает простой вектор, а shape, примененный к каждому, возвращает вложенный вектор.
@Paul Mansour А, хорошо! Я бы получил ошибку домена, если бы попытался использовать векторный вывод как скаляр.
{¯1+⍵-0,¯1↓⍵}⍸
может быть просто ¯1-2-/⍸
В то время как MBaas уже подробно ответил, я подумал, что было бы интересно узнать идиоматическое Dyalog «поезд» ≠⊆⊢
, производное от Комментарий Пола Мансура. Он образует диадическую функцию, которая разбивает свой правый аргумент на вхождения левого аргумента:
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
Если вы привыкли к идиоматическому выражению ≠⊆⊢
, то оно может читаться яснее, чем любое подходящее имя, которое вы можете дать для функции, поэтому вы можете просто использовать выражение в строке:
' ' (≢¨≠⊆⊢) '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
"Самое длинное слово" может быть 2 или 3...