MATLAB - 从字符串元胞数组中提取数字
MATLAB - Extracting numbers from a cell array of strings
我想从文本文件中提取数字。
首先,我读取文件并将其导入为以下形式的元胞数组:
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。
这是使用 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
returns 索引 发生匹配的位置。
第一个 regexp
调用查找出现在 字符串开头 的数字序列。 \d+
表示查找一个或多个数字,^
表示查找 字符串的开头 ,因此将这两者结合起来表示您是在字符串的开头寻找数字序列。我假设字符串的开头是一个整数,所以我们可以摆脱这个。将返回的是一个元胞数组,其中每个条目都是 另一个 匹配元胞数组。如果这可行,我们应该得到一个元胞数组,其中包含一堆 1 x 1 元胞,每个元胞都是开头的数字。
第二个 regexp
调用查找一个数字序列,其中可选地有一组数字 (\d*
),后跟一个可选的小数点 (\.?
),后跟至少 1 个数字 (\d+
) 然后 可选 我们寻找 e
字符、-
字符和另一串数字点(\d+)
。请注意,这些都是通过 (e-\d+)?
组合在一起的,这意味着这个指数级的东西是可选的。此外,整个模式都出现在字符串的 end 处,因此括号将所有这些标记组合在一起并以 $
结尾,这意味着查看 字符串结尾。 *
字符表示查找零次或多次出现,?
字符表示查找零次或一次出现。同样为了保持一致,+
字符表示查找一次或多次出现。
请注意,正则表达式中的 .
字符表示通配符或任何字符。如果明确要匹配小数点,需要在.
字符前加一个\
。因此,正则表达式是在字符串末尾找到模式,其中我们可以选择在可选的小数点之前有一堆数字,然后在这两个可选的东西后面至少有一个数字。这将类似于第一个 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;
我使用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
酷!现在如果你想要第三个和第六个数字,就这样做:
>> third = out(3,:)
third =
3 100
>> sixth = out(6,:)
sixth =
6 0.000612725
以上为您获取整行,但如果您特别想要与 ID 对应的相应数字,只需执行以下操作:
>> third = out(3,2)
third =
100
>> sixth = out(6,2)
sixth =
0.000612725
我想从文本文件中提取数字。 首先,我读取文件并将其导入为以下形式的元胞数组:
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。
这是使用 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
returns 索引 发生匹配的位置。
第一个 regexp
调用查找出现在 字符串开头 的数字序列。 \d+
表示查找一个或多个数字,^
表示查找 字符串的开头 ,因此将这两者结合起来表示您是在字符串的开头寻找数字序列。我假设字符串的开头是一个整数,所以我们可以摆脱这个。将返回的是一个元胞数组,其中每个条目都是 另一个 匹配元胞数组。如果这可行,我们应该得到一个元胞数组,其中包含一堆 1 x 1 元胞,每个元胞都是开头的数字。
第二个 regexp
调用查找一个数字序列,其中可选地有一组数字 (\d*
),后跟一个可选的小数点 (\.?
),后跟至少 1 个数字 (\d+
) 然后 可选 我们寻找 e
字符、-
字符和另一串数字点(\d+)
。请注意,这些都是通过 (e-\d+)?
组合在一起的,这意味着这个指数级的东西是可选的。此外,整个模式都出现在字符串的 end 处,因此括号将所有这些标记组合在一起并以 $
结尾,这意味着查看 字符串结尾。 *
字符表示查找零次或多次出现,?
字符表示查找零次或一次出现。同样为了保持一致,+
字符表示查找一次或多次出现。
请注意,正则表达式中的 .
字符表示通配符或任何字符。如果明确要匹配小数点,需要在.
字符前加一个\
。因此,正则表达式是在字符串末尾找到模式,其中我们可以选择在可选的小数点之前有一堆数字,然后在这两个可选的东西后面至少有一个数字。这将类似于第一个 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;
我使用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
酷!现在如果你想要第三个和第六个数字,就这样做:
>> third = out(3,:)
third =
3 100
>> sixth = out(6,:)
sixth =
6 0.000612725
以上为您获取整行,但如果您特别想要与 ID 对应的相应数字,只需执行以下操作:
>> third = out(3,2)
third =
100
>> sixth = out(6,2)
sixth =
0.000612725