%20%D0%BF%D0%BE%20%D1%81%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D1%8E%20%D1%81%20xparse%20(l3)%20%D0%BF%D1%80%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%BC%20%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%BC%20%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B5.png)
Я понимаю, что обработка строк может быть выполнена либо с LaTeX2e
использованием xstring
, либо expl3
с использованием xparse
(первоначально на основеТема 2013 года «Токенизация и парсинг») Я буду запускать относительно простой макрос синтаксического анализа строк сотни раз в документе, вероятно, во многих компиляциях и во многих документах, и хотел бы узнать, какой метод более эффективен с точки зрения времени и/или вычислений, не считая фиксированного времени загрузки пакетов.
Приближение, основанное на кратком взгляде на xstring
код, было бы весьма кстати от команды 3e. Мне не нужно ничего близкого к точным результатам — это для моего собственного любопытства и просто для того, чтобы убедиться, что я не пытаюсь где-то процарапать кирпичную стену.
Также мне было бы интересно узнать мнения о том, является ли это приложение полезным для сравнения алгоритмов 2e и 3e.
Вот макрос, который я использую xstring
: он делает очень слабое выделение первой буквы (для этой демонстрации — первых двух букв) каждого упоминания ключевых слов и фраз, которые просто загромождали бы страницу, если бы были полностью выделены:
\documentclass{article}
\usepackage{xstring}
%%% capitalize first n letters of each word %%%
% apply operator#3 to string#1 with word separators #2
\newcommand{\Splitstrop}[3][ ]{%
\providecommand\csA{}%
\providecommand\csB{}%
\StrCut{#3}{#1}\csA\csB%
#2{\csA}%
\ifx\csB\empty\else{#1}\Splitstrop[#1]{#2}{\csB}\fi\relax}
% apply operation#3 on first #2 letters of string #1
\newcommand{\Leftstrop}[3][1]{#2{\StrLeft{#3}{#1}}\StrGobbleLeft{#3}{#1}\relax}
\newcommand{\Kw}[1]{\textsc{#1}} %first mention of keyword/phrase
\newcommand{\Kwd}[1]{\Leftstrop[2]{\Kw}{#1}} %single-word 2nd mention: apply \Kw to first two letters of the word (I plan to sc just the first letter, but this is more illustrative)
\newcommand{\Kwds}[1]{\Splitstrop[ ]{\Kwd}{#1}} % keyphrase 2nd mention: apply Kwd to each word (space is word separator)
\begin{document}
Example: We define the \Kw{embiggen} \Kwd{operator} to raise the size of the \Kwd{argument} by one.
This is a reminder not to \Kwds{beg the question} in your definitions (Sec. 2-1): don't say ``We define the \Kwd{embiggen} \Kwd{operator} as the \Kwd{operator} that \Kwd{embiggens}.''
\end{document}
решение1
Я попробовал ваш пример с l3benchmark
:
\documentclass{article}
\usepackage{xstring,l3benchmark}
%%% capitalize first n letters of each word %%%
% apply operator#3 to string#1 with word separators #2
\newcommand{\Splitstrop}[3][ ]{%
\StrCut{#3}{#1}\csA\csB
#2{\csA}%
\ifx\csB\empty\else{#1}\Splitstrop[#1]{#2}{\csB}\fi\relax
}
% apply operation#3 on first #2 letters of string #1
\newcommand{\Leftstrop}[3][1]{#2{\StrLeft{#3}{#1}}\StrGobbleLeft{#3}{#1}\relax}
\newcommand{\Kw}[1]{\textsc{#1}} %first mention of keyword/phrase
\newcommand{\Kwd}[1]{\Leftstrop[2]{\Kw}{#1}} %single-word 2nd mention: apply \Kw to first two letters of the word (I plan to sc just the first letter, but this is more illustrative)
\newcommand{\Kwds}[1]{\Splitstrop[ ]{\Kwd}{#1}} % keyphrase 2nd mention: apply Kwd to each word (space is word separator)
\ExplSyntaxOn
\cs_set_eq:NN \benchmark \benchmark:n
\ExplSyntaxOff
\begin{document}
\benchmark{
Example: We define the \Kw{embiggen} \Kwd{operator} to raise the size of the
\Kwd{argument} by one.
This is a reminder not to \Kwds{beg the question} in your definitions (Sec. 2-1):
don't say ``We define the \Kwds{embiggen operator} as the \Kwd{operator}
that \Kwd{embiggens}.''
}
\end{document}
и expl3
версия
\documentclass{article}
\usepackage{xparse,l3benchmark}
\ExplSyntaxOn
\NewDocumentCommand{\Kw}{m}
{
\kompootor_textsc:n { #1 }
}
\NewDocumentCommand{\Kwd}{m}
{
\kompootor_split:Nnn \kompootor_textsc:n { 2 } { #1 }
}
\NewDocumentCommand{\Kwds}{m}
{
\kompootor_splitstrop:nNn { ~ } \kompootor_textsc:n { #1 }
}
\seq_new:N \l__kompootor_splitstrop_in_seq
\seq_new:N \l__kompootor_splitstrop_out_seq
\cs_new_protected:Nn \kompootor_splitstrop:nNn
{
\seq_set_split:Nnn \l__kompootor_splitstrop_in_seq { #1 } { #3 }
\seq_set_map:NNn \l__kompootor_splitstrop_out_seq \l__kompootor_splitstrop_in_seq
{ \kompootor_leftstrop:Nn #2 { ##1 } }
\seq_use:Nn \l__kompootor_splitstrop_out_seq { #1 }
}
\cs_new_protected:Nn \kompootor_leftstrop:Nn
{
\kompootor_split:Nnn #1 { 2 } { #2 }
}
\cs_new:Nn \kompootor_split:Nnn
{
#1 { \tl_range:nnn { #3 } { 1 } { #2 } }
\tl_range:nnn { #3 } { #2+1 } { -1 }
}
\cs_new_protected:Nn \kompootor_textsc:n { \textsc { #1 } }
\NewDocumentCommand{\benchmark}{+m}{\benchmark:n{#1}}
\ExplSyntaxOff
\begin{document}
\benchmark{
Example: We define the \Kw{embiggen} \Kwd{operator} to raise the size of the
\Kwd{argument} by one.
This is a reminder not to \Kwds{beg the question} in your definitions (Sec. 2-1):
don't say ``We define the \Kwds{embiggen operator} as the \Kwd{operator}
that \Kwd{embiggens}.''
}
\end{document}
Результатом является
0.00338 seconds (1.1e4 ops)
для xstring
внедрения и
0.00187 seconds (6.29e3 ops)
для expl3
реализации.
Вывод идентичен (удаление \benchmark
):