MATLAB Answers

Collapsing nested cell array values into simple numerical array

2 ビュー (過去 30 日間)
Michael
Michael 2019 年 12 月 4 日
Edited: Michael 2019 年 12 月 4 日
I have used regexp to find some numbers in each element of a cell array. However, the result of the regexp is a nested cell array such as the following:
>> celldisp(a)
a{1}{1}{1} =
5
a{2}{1}{1} =
36
All I want is to have the result collapsed into the simple numerical array [5 36] but I have been unable to get the right syntax.I have tried things like the following but the nesting seems to cause issues:
>> b=[a{:}{1}{1}]
Expected one output from a curly brace or dot indexing expression, but there were 2 results.
>> b=cell2mat(a{:}{1}{1})
Expected one output from a curly brace or dot indexing expression, but there were 2 results.
>> b=cell2mat(a)
Error using cell2mat (line 52)
CELL2MAT does not support cell arrays containing cell arrays or objects.
I could certainly use a loop to iterate through it, but it seems like there should be some very simple syntax that does the trick.

  0 件のコメント

サインイン to comment.

採用された回答

Stephen Cobeldick
Stephen Cobeldick 2019 年 12 月 4 日
編集済み: Stephen Cobeldick 2019 年 12 月 4 日
"I have used regexp to find some numbers in each element of a cell array."
If the regular expression only needs to match once, then use the 'once' option to remove one level of nesting.
"but it seems like there should be some very simple syntax that does the trick"
Not really: nesting data in container arrays makes it difficult to access.
>> C = [a{:}];
>> C = [C{:}];
>> V = [C{:}]
V =
5 36
Read these to know more:

  3 件のコメント

Michael
Michael 2019 年 12 月 4 日
I think I've got it. Your solution as provided assumed I already had numbers, but regexp (at least the way I had used it) had strings which happened to contain numeric characters. So after the last step I ended up with:
>> V = [C{:}]
V =
'536'
I have done the following based on your 'once' suggestion and an adjustment to your example code which gets me to where I wanted to be:
>> a=regexp(errors,'Iteration: (\d*)','tokens','once')
a =
1×2 cell array
{1×1 cell} {1×1 cell}
>> C = [a{:}]
C =
1×2 cell array
{'5'} {'36'}
>> V = cellfun(@str2num,C)
V =
5 36
It definitely works, but it still seems like a lot of clunky syntax for what I thought would be simple. Was there a way to do the initial regexp that would have gotten to the end result more cleanly?
Stephen Cobeldick
Stephen Cobeldick 2019 年 12 月 4 日
Using str2double handles the cell array of char vectors directly:
>> C = {'hello iter: 5 blah','world iter: 23 blah'};
>> D = regexp(C,'iter: (\d*)','tokens','once');
>> V = cellfun(@str2num,[D{:}]) % your code
V =
5 23
>> V = str2double([D{:}]) % no need for CELLFUN
V =
5 23
"Was there a way to do the initial regexp that would have gotten to the end result more cleanly?"
Use a look-behind assertion, then you can avoid one more layer of cell arrays:
>> D = regexp(C,'(?<=iter: )\d*','match','once');
>> V = str2double(D)
V =
5 23
Michael
Michael 2019 年 12 月 4 日
I hadn't realized the (several) important differences between str2num and str2double - it's an excellent suggestion that's far superior to using cellfun.
I know how powerful regexp is but I've never had the time to master it and hadn't considered the look-behind assertion. I had just come up with something that gave me the items I was looking for instead of getting those items the best way.
Based on all your wonderful suggestions, I now have the elegant one-liner I was hoping for:
>> str2double(regexp(errors,'(?<=Iteration: )\d*','match','once'))
ans =
5 36

サインイン to comment.

More Answers (0)

サインイン してこの質問に回答します。

タグ

製品


リリース

R2019a

Translated by