Есть ли функция, которая ищет последовательность элементов для подпоследовательности?Ищу аналог StringPosition
для List
с.В моем текущем приложении я работаю со списками целых чисел, но меня будет интересовать общая функция FindSequence[list, pattern, n]
, которая найдет первые n
вхождения pattern
в list
.
* 1009.* Вот игрушечный пример:
Создайте некоторые данные:
In[1]:= $HistoryLength = 0
Out[1]= 0
In[2]:= Timing[digits = First[RealDigits[\[Pi], 2, 10000000]];]
Out[2]= {26.5, Null}
Давайте преобразуем их в строку, чтобы мы могли сравнить с StringPosition
.Это очень медленно для памяти.(Память освобождается после завершения оценки.)
In[3]:= Timing[str = StringJoin[ToString /@ digits];]
Out[3]= {43.813, Null}
Я ищу эту последовательность:
In[4]:= patt = {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0,
1, 0, 1, 1};
In[5]:= strpatt = StringJoin[ToString /@ patt];
Поиск строки очень быстрый:
In[6]:= StringPosition[str, strpatt] // Timing
Out[6]= {1.047, {{5737922, 5737943}}}
Это простая реализация поиска числовых массивов.Это медленнее, чем StringPosition
:
In[7]:= Timing[
corr = ListCorrelate[patt, digits];
Select[Flatten@Position[corr, patt.patt],
digits[[# ;; # + Length[patt] - 1]] === patt &]
]
Out[7]= {2.234, {5737922}}
Сводка:
- Есть ли встроенная функция, которая ищет в списках подпоследовательности?
- Если нет, то какова быстрая и элегантная реализация для числовых списков (моя практическая проблема)?
- Как насчет универсальных списков, которые могут содержать что-нибудь?(Здесь есть две возможности: только «статические» шаблоны, такие как
{1,0,1}
, или общие, такие как {1,_,1}
, хотя эти последние могут создавать сложности.)
Я ожидаю, что их будет многорешения, некоторые быстрые, некоторые более элегантные, некоторые более общие: -)
Смежные вопросы:
Интересное чтение:
РЕДАКТИРОВАТЬ:
Я только что нашелбез документов LongestCommonSubsequencePositions
.LongestCommonSubsequencePositions[a, b]
найдет самую длинную общую подпоследовательность списков a
и b
и вернет позицию своего первого вхождения только в a
и b
.(Документированный LongestCommonSubsequence
, о котором я не знал, будет возвращать только саму подпоследовательность, а не ее позицию.)
Это медленнее, чем альтернативы, описанные выше, но оно работает с общими списками, которые могут содержатьвыражение.
In[57]:= LongestCommonSubsequencePositions[digits, patt] // Timing
Out[57]= {5.25, {{5737922, 5737943}, {1, 22}}}