【问题标题】:How to select rows from array where string contains number in range: MATLAB如何从数组中选择行,其中字符串包含范围内的数字:MATLAB
【发布时间】:2018-02-14 14:12:48
【问题描述】:

我有这个数组:

AB01    4   7
AB02    3   4
AB02    2   4
AB03    9   5
AB01    3   3
AB04    3   2
AB05    4   1
AB03    4   1
AB05    3   4
AB04    1   5

我有 2 个数字输入,它们确定最小值和最大值。例如,如果我设置第一个输入n1 = 2 和第二个输入n2 = 4,这意味着我想要在第一列中具有AB02AB03AB04 值的行,我将得到如下输出这个:

AB02    3   4
AB02    2   4
AB03    9   5
AB04    3   2
AB03    4   1
AB04    1   5

我不知道如何从AB02-AB04 创建范围值,因为它不是一个数字。非常感谢您的帮助。


编辑:我正在尝试使用此脚本,我知道我的逻辑索引不正确,但我被卡住了。

col1 = 3;
fmt = repmat('%s',1,col1);
enter cofid = fopen('Document2.txt', 'rt');de here
filecolumn = textscan(fid, fmt, 'Delimiter', ' ');
fclose(fid);
FF = horzcat(filecolumn{:});

y1 = input('INPUT1: ')
y = sprintf('AB%.2d',y1)
z1 = input('INPUT2: ')
z = sprintf('AB%.2d',z1)
for o = y:z
   while o == 1 
      index = find(strcmp(FF,o))
   end
   ff = FF(index,:)
end

【问题讨论】:

  • 这个问题可以分成不同的子问题:(1)从字符串中提取一个数字(2)数组中元素的范围检查(3)逻辑索引

标签: arrays string matlab indexing


【解决方案1】:

让我们从单元格数组中的字符串末尾提取数字,您可以使用正则表达式来保持一般性,但我会假设您总是在 4 位数字末尾有一个 2 位数字像你展示的那样的字符串......

% Your data
M = {'AB01'  4   7
     'AB02'  3   4
     'AB02'  2   4
     'AB03'  9   5
     'AB01'  3   3
     'AB04'  3   2
     'AB05'  4   1
     'AB03'  4   1
     'AB05'  3   4
     'AB04'  1   5};
% Extracting numbers, using cellfun to operate on each element of the cell array
nums = cellfun(@(r)str2num(r(3:4)), M(:,1));
>> nums = [1
           2
           2
           % ... others ...
           4]

现在我们可以使用逻辑索引来访问您想要的行

n1 = 2; % lower bound
n2 = 4; % upper bound
% Create logical array, true where nums is in range [n1,n2], false otherwise    
idx = nums >= n1 & nums <= n2;

并检索M的行

output = M(idx,:);
>> output = 
   {'AB02'  3  4
    'AB02'  2  4
    'AB03'  9  5
    'AB04'  3  2
    'AB03'  4  1
    'AB04'  1  5}

作为参考,没有输出的所有代码可能看起来像这样:

% Input values
n1 = 2; n2 = 4;
% Your data stored in cell array M, get numbers
nums = cellfun(@(r)str2num(r(3:4)), M(:,1));
% Get rows within range
output = M(nums >= n1 & nums <= n2, :);

【讨论】:

  • str2num 使用eval。请改用str2double
  • 更好的事件是使用字符串并在其上调用双精度。 x = 个(1000); str = 字符串(x); cll = cellstr(str);抽动;双(str);目录;抽动; str2double(cll); toc 经过的时间是 0.534203 秒。经过的时间是 16.009992 秒。
  • @matlabbit 我没有 2016b+(string 需要)来测试它,但在此之前调用 double 在一串数字上将返回其 ASCII 值的数组...所以这个建议似乎有问题
  • @Wolfie 在字符串上调用 double 是从字符串到 double 的首选方法。它将数字的文本表示形式转换为数字。在字符数组上调用 double 仍然会为您提供 ascii 值。此外,在字符串上调用 double 可以更正确地将逗号作为千位分隔符处理:str2double(",2,,0,") 得到 20。double(",2,,0,") 得到 NaN。
  • @Wolfie 另外(并且稍微不相关),现在您可以在 double 上调用 string 以将其转换为字符串,您可以执行 "Hello " + 42 从而得到 "Hello 42"。当存在适当的字符串转换并且没有调度优先级问题时,字符串的加号将执行隐式转换。不再需要使用字符串来限制 num2str。
【解决方案2】:

我建议您使用表格而不是元胞数组,并使用带有 TextType 字符串的 tableread 来导入数据。使用字符串提取值稍微简单一些(从 16b 开始提供)。如果您要处理大量数据,字符串也会更快。

lower_bound = 2;
upper_bound = 4;

data = {'AB02'  3  4
        'AB02'  2  4
        'AB03'  9  5
        'AB04'  3  2
        'AB03'  4  1
        'AB04'  1  5};

data = cell2table(data,'VariableNames',{'x','y','z'});
data.x = string(data.x);

value = extractAfter(data.x,2);
value = double(value);

data = data(value >= lower_bound & value <= upper_bound,:)

data =

  6×3 table

      x       y    z
    ______    _    _

    "AB02"    3    4
    "AB02"    2    4
    "AB03"    9    5
    "AB04"    3    2
    "AB03"    4    1
    "AB04"    1    5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-23
    • 2020-04-27
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    相关资源
    最近更新 更多