MATLAB - 从字符串的单元格数组中提取数字

时间:2015-06-01 13:42:47

标签: string matlab numbers cell

我想从文本文件中提取一个数字。 首先,我读取文件并导入为以下形式的单元格数组:

A = {
        '1   0   0   0   -   0:  0.000741764'
        '2   0   0   0   -   0:          100'
        '3   0   0   0   -   0:          100'
        '4   0   0   0   -   0:          100'
        '5   0   0   0   -   0:   0.00124598'
        '6   0   0   0   -   0:  0.000612725'
        '7   0   0   0   -   0:  0.000188365'
        '8   0   0   0   -   0:            0'
        '9   0   0   0   -   0:            0'
        '10   0   0   0   -   0:            0'
        '11   0   0   0   -   0:            0'
        '12   0   0   0   -   0:            0'};

我需要根据左整数的值得到右边的数字。 例如,我需要知道对应于3和6(100和0.000612725)的值:

'3   0   0   0   -   0:          100'
'6   0   0   0   -   0:  0.000612725'

这是我的代码:

clear all
close all
clc

A = {
        '1   0   0   0   -   0:  0.000741764'
        '2   0   0   0   -   0:          100'
        '3   0   0   0   -   0:          100'
        '4   0   0   0   -   0:          100'
        '5   0   0   0   -   0:   0.00124598'
        '6   0   0   0   -   0:  0.000612725'
        '7   0   0   0   -   0:  0.000188365'
        '8   0   0   0   -   0:            0'
        '9   0   0   0   -   0:            0'
        '10   0   0   0   -   0:            0'
        '11   0   0   0   -   0:            0'
        '12   0   0   0   -   0:            0'};

THREE = 3;
SIX = 6;

M  = cellfun(@str2num, A, 'UniformOutput', false);
Values = cell2mat(M);

Index_3 = find(Values(:,1) == SIX);
Index_6 = find(Values(:,1) == SIX);

sp_3 = strsplit(A{Index_3},':');
sp_6 = strsplit(A{Index_6},':');

VALUE_3 = str2double(sp_3(end));
VALUE_6 = str2double(sp_6(end));

但我得到了一个错误:

Error using cat
Dimensions of matrices being concatenated are not consistent.
Error in cell2mat (line 84)
            m{n} = cat(1,c{:,n});
Error in test (line 23)
Values = cell2mat(M); 

,这是因为:

M = 
    [1x4   double]
    [1x104 double]
    [1x104 double]
    [1x104 double]
    [1x4   double]
    [1x4   double]
    [1x4   double]
    [1x4   double]
    [1x4   double]
    [1x4   double]
    [1x4   double]
    [1x4   double]

我试过了:

str2double

相反,但我得到M中所有值的NaN。

1 个答案:

答案 0 :(得分:3)

这是使用regular expressions的完美案例。正则表达式是在文本中寻找模式的强大工具。在您的情况下,您首先想要找到的是开始字符串的数字。接下来,您要在字符串末尾找到相应的数字。您还在评论中提到,您可以使用指数表示法获取数字(类似2.50652e-007)。这也可以轻松处理,我将把它添加为您的单元格数组中的另一个条目,以证明这是有效的。

我将如何进行是因为我将处理整个单元格数组。我之所以这样做,是因为我确定你需要查看其他数字,而不仅仅是第三和第六项,所以如果我们先这样做,那么它会非常容易你得到你需要的其他东西。

我们可以在两个正则表达式regexp调用中提取开始值和结束值,以提取开头和结尾,如下所示:

%// Your code to define A and also new entry with exponential notation
A = {
        '1   0   0   0   -   0:  0.000741764'
        '2   0   0   0   -   0:          100'
        '3   0   0   0   -   0:          100'
        '4   0   0   0   -   0:          100'
        '5   0   0   0   -   0:   0.00124598'
        '6   0   0   0   -   0:  0.000612725'
        '7   0   0   0   -   0:  0.000188365'
        '8   0   0   0   -   0:            0'
        '9   0   0   0   -   0:            0'
        '10   0   0   0   -   0:            0'
        '11   0   0   0   -   0:            0'
        '12   0   0   0   -   0:            0',
        '13   0   0   0   -   0: 2.50652e-007'};

%// Begin new code
beginStr = regexp(A, '^\d+', 'match');
endStr = regexp(A, '(\d*\.?\d+(e-\d+)?)$', 'match');

看起来有点复杂,但很容易解释。 regexp默认情况下接受两个参数:字符串或单元格数组(例如您的情况)和要搜索的模式。我还选择了标志'match',因为我想要返回实际的字符串。默认情况下,regexp会返回匹配发生位置的索引

第一次regexp次调用会查找在字符串的开头处出现的数字序列。 \d+表示查找一个或多个数字,^表示在字符串的开头查看,因此将这两个结合起来表示您正在寻找对于字符串开头的数字序列。我假设字符串的开头是一个整数,所以我们可以侥幸逃脱。将返回的是一个单元格数组,其中每个条目都是另一个匹配的单元格数组。如果这样做,我们应该得到一个包含1 x 1个单元格的单元格数组,每个单元格都是开头的数字。

第二个regexp调用会查找一系列数字,以便有一堆数字(\d*),后跟一个可选的小数点(\.?),然后是至少有1个号码(\d+)然后可选我们会在此之后查找e个字符,-字符和另一堆数字{{1} }。请注意,这些都是通过(\d+)组合在一起的,这意味着这个指数内容是可选的。此外,整个模式都出现在字符串的 end ,因此括号将所有这些标记组合在一起并以(e-\d+)?结尾,这意味着查看结尾串即可。 $字符表示查找零次或多次出现,*字符表示查找零次或一次出现。同样,?字符表示要查找一个或多个匹配项。

请注意,正则表达式中的+字符表示通配符或任何字符。如果您明确希望与小数点匹配,则需要在.字符前添加\。因此,正则表达式是在字符串末尾找到模式,我们可以选择在可选小数点之前有一堆数字,然后在这两个可选项之后至少有一个数字。这将类似于第一个.调用的输出,但在字符串的末尾有数字。

让我们使用regexp进行仔细检查:

celldisp

对我来说很好看!现在,您的最终任务是将数字转换为double。我们可以使用>> format compact >> celldisp(beginStr) beginStr{1}{1} = 1 beginStr{2}{1} = 2 beginStr{3}{1} = 3 beginStr{4}{1} = 4 beginStr{5}{1} = 5 beginStr{6}{1} = 6 beginStr{7}{1} = 7 beginStr{8}{1} = 8 beginStr{9}{1} = 9 beginStr{10}{1} = 10 beginStr{11}{1} = 11 beginStr{12}{1} = 12 beginStr{13}{1} = 13 >> celldisp(endStr) endStr{1}{1} = 0.000741764 endStr{2}{1} = 100 endStr{3}{1} = 100 endStr{4}{1} = 100 endStr{5}{1} = 0.00124598 endStr{6}{1} = 0.000612725 endStr{7}{1} = 0.000188365 endStr{8}{1} = 0 endStr{9}{1} = 0 endStr{10}{1} = 0 endStr{11}{1} = 0 endStr{12}{1} = 0 endStr{13}{1} = 2.50652e-007 电话,就像您为我们做的那样:

cellfun

beginNumbers = cellfun(@(x) str2double(x{1}), beginStr); endNumbers = cellfun(@(x) str2double(x{1}), endStr); beginNumbers将包含我们转换后的号码。让我们将这些放入矩阵并显示它的样子:

endNumbers

我使用out = [beginNumbers endNumbers]; format long g; 来显示尽可能多的有效数字。这就是我们得到的:

format long g

酷!现在,如果您想要第三个和第六个数字,只需执行:

>> out

out =

                         1               0.000741764
                         2                       100
                         3                       100
                         4                       100
                         5                0.00124598
                         6               0.000612725
                         7               0.000188365
                         8                         0
                         9                         0
                        10                         0
                        11                         0
                        12                         0
                        13               2.50652e-07

以上内容为您提供整行,但如果您特别想要与ID一起使用的相应数字,请执行以下操作:

>> third = out(3,:)

third =

     3   100

>> sixth = out(6,:)

sixth =

                         6               0.000612725