У меня возникли проблемы с индексацией строк, содержащихся в массиве ячеек, с помощью функции cellfun. У меня есть массив ячеек со строками различного содержания, и я пытаюсь извлечь числа между словами «вход» и «дБм» в следующем примере, где в интересующих строках всегда есть слово «внимание». (Мое фактическое использование состоит из десятков строк, но это упрощенный пример). Я могу получить индексы ячеек, содержащих «atten», используя функцию «contains», которая работает как положено. Я также могу получить индексы в каждой ячейке, которые хочу извлечь, с помощью функции «strfind» внутри cellfun, которые показаны ниже как переменные «st» и «sp».
Но я не могу использовать значения «st» и «sp» для извлечения интересующих чисел, а именно -70,6, -67,5 и -69,9 в этом примере. Возможен ли этот тип индексации с помощью cellfun? Или мне просто использовать цикл for?
Код с комментариями внизу показывает значения, которые я сейчас получаю в out_cell_array, и что мне нужно получить.
d = {'some random text';...
'atten 16.0 input -70.6 dBm';...
'atten 0.0 input -67.5 dBm';...
'atten 13.0 input -69.9 dBm';...
'some other random text'};
idx = find(contains(d,'atten'));
st = cellfun(@(x) strfind(x, 'input'), d(idx)) + 6; % index starting 6 to the right "input"
sp = cellfun(@(x) strfind(x, 'dBm'), d(idx)) - 2; % index starting 2 to the left of "dBm"
out_cell_array = cellfun(@(x){x(st:sp)}, d(idx));
%values after running above. everything works until the last "cellfun" line, which isn't indexing how I want
% disp(idx') 2 3 4
% disp(d(idx)') 'atten 16.0 input -70.6 dBm' 'atten 0.0 input -67.5 dBm' 'atten 16.0 input -69.9 dBm'
% disp(st') 18 17 18
% disp(sp') 22 21 22
% disp(out_cell_array') '-70.6' '67.5 ' '-69.9' <-- is not indexing using the values of st and sp
%%%% I want this:
% out_cell_array = {d{2}(18:22); d{3}(17:21); d{4}(18:22)};
% disp(out_cell_array') '-70.6' '-67.5' '-69.9'
Хорошо, это нормально. Я буду использовать цикл for. Спасибо.
Значения x, st и sp в вашем последнем файле CellFun не совпадают. Попробуй это:
x = d(idx); % extract the appropriate cells first
arrayfun(@(k)x{k}(st(k):sp(k)),(1:numel(st))','uni',false') % then extract the strings
Или, если вы действительно хотите использовать CellFun,
cellfun(@(x,st,sp){x(st:sp)}, d(idx),num2cell(st),num2cell(sp))
Спасибо. Я не смог использовать другое предложение со «совпадениями», потому что я использую более старую версию Matlab, так что это мой победитель :)
Вы можете использовать строковые функции match вместе с некоторыми шаблонами , а также ExtractBetween, чтобы сделать это довольно просто:
% Find all elements that start with "atten", and have "input" and "dBm"
ismatch = matches(d, "atten" + wildcardPattern + "input" + wildcardPattern + "dBm");
% Pick out whatever is between "input" and "dBm" and convert it to double.
str2double(extractBetween(d(ismatch), "input", "dBm"))
Спасибо. Я мог бы использовать функцию совпадений, потому что моя версия Matlab использует какой-то метод Java. Но я буду иметь это в виду, если моя компания когда-нибудь обновит нашу лицензию :) >> совпадение — это метод Java % java.lang.String метод
Это позор. Я думаю, что возможности обработки текста в последних версиях MATLAB значительно упрощают жизнь.
Всегда сначала следует писать простой цикл, если только векторизация не является тривиальной и очевидной. Если затем окажется, что он работает слишком медленно (узкое место в вашем коде), вы можете начать думать о том, чтобы приложить усилия к векторизации. В современных версиях MATLAB векторизованный код часто ненамного быстрее, чем код цикла, а иногда и намного медленнее (когда требуются очень большие промежуточные массивы), поэтому часто не стоит прилагать усилия к векторизации.