How to find the largest index into a cell array, pointing to an element after which all subsequent elements are empty?
1 Ansicht (letzte 30 Tage)
Ältere Kommentare anzeigen
Minh Tran
am 18 Sep. 2018
Kommentiert: Minh Tran
am 18 Sep. 2018
I'm writing a function that parses a text file containing key-value-value tuples that are separated by 2 delimiters. The second delimiter is optional. Each 3-tuple is separated by a newline. The output array of size M x 3 (for a text file containing M key-value-value tuples) must not containing unused (empty) cell arrays.
ML_Configfile.jpg shows what a config file looks like (delimiter is the colon).
ML_matvalues.jpg indicates what the output values `keys`, `values`, `units` look like when ran with that text file as input.
ML_End.jpg shows what the output looks like before some lines of my code executes to remove empty, preallocated cells. In this case, cells below 55 needs to be removed.
Here is the function:
function [options_array, keys, values, units] = parseconfig(config_filename, delimiter, max_num_lines)
% TEST CASES:
% case_1 = ''
% case_2 = '::'
% case_3 = ' : : '
% case_4 = 'System_Name : Santos Basin'
% case_5 = 'Look_Back_End : 0.0 : days'
% case_5 = 'Speed_Threshold : 3.0 : knots % This is an inline comment'
% case_6 = 'Author : "Johnny Appleseed"'
% case_7 = '%This is an inline comment'
% case_8 = '%Bad comment : '
% case_9 = ': %Bad comment : '
% case_10 = 'ValidField : %Bad comment : '
% case_11 = 'ValidField : ValidValue : %Bad comment'
% Preallocate cell array for each key-value pair
keys = cell(max_num_lines, 1);
values = cell(max_num_lines, 1);
units = cell(max_num_lines, 1);
line_number = 1;
fh = fopen(config_filename, 'r');
while (line_number <= max_num_lines)
line = fgetl(fh);
if (isempty(line)) continue, end
if (~ischar(line)), break, end
fields = textscan(line, '%s%s%[^%]', ...
'Delimiter', delimiter, 'CommentStyle', '%');
[fieldname, fieldvalue, fieldunit] = fields{:};
% Append trimmed values to their return cell arrays
if ~isempty(strtrim(fieldname))
keys{line_number} = strtrim(fieldname);
values{line_number} = strtrim(fieldvalue);
units{line_number} = strtrim(fieldunit);
end
line_number = line_number + 1;
end
fclose(fh);
% Find the greatest index of last-occuring empty cell array of
% `fieldnames`, `fieldvalues`, and `fieldunits`
% Locate & delete unused, preallocated cells (reshaping cell array)
keys = keys(~cellfun('isempty', keys));
values = values(~cellfun('isempty', values));
units = units(~cellfun('isempty', units));
% Output array
options_array = [keys values units];
end
The issue with
keys = keys(~cellfun('isempty', keys));
values = values(~cellfun('isempty', values));
units = units(~cellfun('isempty', units));
is that it doesn't preserve the empty cells in column 3 (`units`) when the delimiter is omitted in the text file. So if I somehow found the largest index pointing to the start of the empty cell array elements, I can slice-out the empty cell array elements from each of the three cell arrays.
0 Kommentare
Akzeptierte Antwort
ADragon
am 18 Sep. 2018
I think find() will help you get what you want
idx1 = find(~cellfun('isempty',keys),1,'last');
idx2 = find(~cellfun('isempty',values),1,'last');
idx3 = find(~cellfun('isempty',units),1,'last');
lastidx = max([idx1 idx2 idx3]);
1 Kommentar
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Cell Arrays finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!