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

String MATLAB-从字符串单元格数组中提取数字,string,matlab,numbers,cell,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

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

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):

这是我的代码:

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。

这是一个完美的使用案例。正则表达式是在文本中寻找模式的强大工具。在您的例子中,首先要查找字符串开头的数字。接下来,您希望在字符串的末尾找到相应的数字。您在评论中还提到,您可能会得到指数表示法的数字(类似于
2.50652e-007
)。这也很容易处理,我将把它作为另一个条目添加到您的单元格数组中,以演示它的工作原理

我将如何处理整个单元阵列。我这样做是因为我相信你需要看其他的数字,而不仅仅是第三和第六个条目,所以如果我们先这样做,那么你就很容易得到你需要的其他东西

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

%// 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');
看起来有点复杂,但很容易解释<默认情况下,code>regexp接受两个参数:字符串或字符串单元格数组(如您的大小写)和要搜索的模式。我还选择了标志
'match'
,因为我希望返回实际的字符串。默认情况下,
regexp
返回匹配位置的索引

第一个
regexp
调用查找字符串开头出现的一系列数字
\d+
表示查找一个或多个数字,
^
表示查找字符串开头的,因此将这两者结合起来表示您正在查找字符串开头的数字序列。我假设字符串的开头是一个整数,这样我们就可以不受影响了。将返回一个单元格数组,其中每个条目都是另一个匹配的单元格数组。如果这是可行的,我们应该得到一个包含一堆1 x 1个单元格的单元格数组,每个单元格都是开头的数字

第二个
regexp
调用查找一个数字序列,这样就可以有一组可选的数字(
\d*
),后跟一个可选的小数点(
\?
),后跟至少一个数字(
\d+
),然后可选地查找一个
e
字符,
-
字符和这一点之后的另一组数字
(\d+)
。请注意,这些都是通过
(e-\d+?
组合在一起的,这意味着这些指数内容是可选的。此外,整个模式都出现在字符串的结尾,因此括号将所有这些标记组合在一起,并以
$
结尾,这意味着查看字符串的结尾
*
字符表示查找零次或多次出现,而
字符表示查找零次或一次出现。同样为了保持一致,
+
字符表示查找一个或多个事件

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

让我们使用
celldisp
再次检查:

>> 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;
我使用
格式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
酷!现在,如果您想要第三个和第六个数字,只需执行以下操作:

>> third = out(3,:)

third =

     3   100

>> sixth = out(6,:)

sixth =

                         6               0.000612725
>> third = out(3,2)

third =

   100

>> sixth = out(6,2)

sixth =

               0.000612725
以上内容为您提供了整行内容,但如果您特别想要ID对应的数字,只需执行以下操作:

>> third = out(3,:)

third =

     3   100

>> sixth = out(6,:)

sixth =

                         6               0.000612725
>> third = out(3,2)

third =

   100

>> sixth = out(6,2)

sixth =

               0.000612725

我不会在我所有的答案中加上这么多的信息:D解释得很好+1@rayryeng一如既往的辉煌!谢谢@SanthanSalai-谢谢:)正则表达式我觉得它们总是需要很多解释。这是一种很多人(包括我在内)都不太理解的黑色艺术,因此使用它们的问题需要解释,因为这两个
regexp
调用非常强大,但每个调用使用的模式看起来像是一门非常难学的外语。我觉得如果你能解释发生了什么,这不仅有助于我强化这个概念,也有助于其他人了解正则表达式的强大功能。谢谢你的投票:)“包括我!”哈哈,你太谦虚了!!:)@ViharChervenkov-完成。看一看。它需要对第二个正则表达式稍加修改。我还添加了一个示例来说明它的工作原理。