Например, предположим, что переменная strings
является ячейка, содержащая строки, например:Как отфильтровать элементы, которые не соответствуют регулярному выражению?
strings = {'alpha' 'basis' 'colic' 'druid' 'even' 'fluff' 'golf'};
Я хочу, чтобы фильтровать strings
так, чтобы в конечном итоге только со строками, которые имеют соответствующие первый и последний символы. IOW, результат от этой операции должен быть
{'alpha' 'colic' 'druid' 'fluff'}
В целом,
Я хочу, чтобы фильтровать массив ячеек строк, чтобы удалить все строки, которые не соответствуют некоторому регулярному выражению.
Для приведенного выше примера, я могу получить желаемый результат с помощью следующего логического массива
~~cellfun(@numel, regexp(strings, '^(.).*\1$'))
IOW,
>> strings(~~cellfun(@numel, regexp(strings, '^(.).*\1$')))
ans =
'alpha' 'colic' 'druid' 'fluff'
Но ~~cellfun(@numel, regexp(strings, '^(.).*\1$'))
является нечитаемым уродство.
Есть ли более четкий способ фильтрации массива ячеек, чтобы сохранить соответствия регулярному выражению?
EDIT: на основе ответа excaza, я определил следующие функции:
% grep.m
function filtered = grep(pattern, cellarray)
%GREP find matches to PATTERN in a cell array of strings.
% GREP(PATTERN, CELLARRAY) returns a cell array
% containing all the strings in CELLARRAY that match the
% regular expression PATTERN. CELLARRAY is expected to
% be a cell array of strings.
filtered = cellarray(matchq(cellarray, pattern));
end
% matchq.m
function yn = matchq(string, pattern)
%MATCHQ predicate stating whether STRING matches PATTERN.
% If STRING is a single string, MATCHQ(STRING, PATTERN)
% returns a logical value corresponding to whether or not
% STRING matches pattern. If STRING is a cell array of
% strings, MATCHQ(STRING, PATTERN) returns a logical vector
% whose i-th entry equals MATCHQ(STRING{i}, PATTERN).
if ischar(string)
yn = ~isempty(regexp(reshape(string, 1, []), pattern, 'match'));
else
assert(iscellstr(string));
yn = cellfun(@(s) matchq(s, pattern), string);
end
end
С этими определениями,
>> grep('^(.).*\1$', strings)
ans =
'alpha' 'colic' 'druid' 'fluff'
FWIW, grep
еще "работает", даже если strings
состоит из условно-символьные векторы характера:
>> grep('^(.).*\1$', {['aus';'tra';'lia'], ['basis']', ['ce';'lt';'ic'], ...
['dia';'led'], 'early', ['foo';'lpr';'oof'], ...
['gyp';'sum']})
ans =
[3x3 char] [3x2 char] [2x3 char] [3x3 char]
>> cellfun(@(c) reshape(c', [], 1)', ans, 'UniformOutput', false)
ans =
'australia' 'celtic' 'dialed' 'foolproof'
Используйте ' '^ ((?!.). * \ 1 $) ''или''^(?! (.). * \ 1 $). * '' –
@ WiktorStribiżew:' regexp ('^(?! (.). * \ 1 $) ', строки) 'оценивается эквивалентом' repmat ({[]}, 1, numel (строки)) '. Тоже для 'regexp ('^ (?! (.). * \ 1 $). *', Строки)'. – kjo