Converting rough strings to exact strings

I have a string array of filenames which are names in an semi-consistent manner, e.g.:
AllFiles
AllFiles =
4x1 string array
"textIdontCareAbout_Phenolic32_Group5_textIdontCareAbout"
"textIdontCareAbout_P1_textIdontCareAbout"
"textIdontCareAbout_Epx2_G3_textIdontCareAbout"
"textIdontCareAbout_Epoxy_105_textIdontCareAbout"
Im trying to figure out how to extract & convert the inconsistent substrings of interest (the stuff between "textIdontCareAbout") into a consistent format, e.g.:
AllFiles
AllFiles =
4x1 string array
"P32G5"
"P1"
"E2G3"
"E105"
I had been avoiding using regexp, but having caved and decided to work with that, I'm trying to figure out an elegant way to do this conversion. At present the only thing I can see working is manually checking for each possible phrasing style I see when manualy searching through the data I have at present.
Is there a better way to go about this, or even just some suggestions to how to define the regexp in a way to have as few searches as possible?

4 Comments

Using regular expressions is the only way I can think to attack this. And, at the risk of stating the obvious ... you can't write the regular expression code until you can precisely define the rule for the expression you are trying to identify. So, that's the first step.
It seems that the rule might be ...
  • only the substring between the outermost underscores
  • all the digits
  • only the capitalized letters
I don't want to bother figuring out a regular expression that does that, though, if that does not seem like the fully general rule you need.
Yeah, I was (pessimistically) expecting that to be the answer. Sadly, that "textIdontCareAbout" contains both numbers and underscores (old filling system requires underscore instead of whitespace). So, with you having given me the understanding that there likely isn't a better way to go about this, I'll put my nose to the grindstone developing a cell array of expressions to feed regexp based on the file names I've seen. There's a few checks I can run to narrow down multiple invocations of regexp (e.g. contains(AllFiles,'Group')), so at least there's that.
There may be a way to do this with string operations. Hard to tell w/o knowing the rule(s) to apply for what to keep and what to discard from a single string. For example, supposing that @the cyclist has the correct rules, one could do
AllFiles = [
"textIdontCareAbout_Phenolic32_Group5_textIdontCareAbout"
"textIdontCareAbout_P1_textIdontCareAbout"
"textIdontCareAbout_Epx2_G3_textIdontCareAbout"
"textIdontCareAbout_Epoxy_105_textIdontCareAbout"]
AllFiles = 4×1 string array
"textIdontCareAbout_Phenolic32_Group5_textIdontCareAbout" "textIdontCareAbout_P1_textIdontCareAbout" "textIdontCareAbout_Epx2_G3_textIdontCareAbout" "textIdontCareAbout_Epoxy_105_textIdontCareAbout"
AllFiles = extractAfter(AllFiles,"_")
AllFiles = 4×1 string array
"Phenolic32_Group5_textIdontCareAbout" "P1_textIdontCareAbout" "Epx2_G3_textIdontCareAbout" "Epoxy_105_textIdontCareAbout"
AllFiles = reverse(extractAfter(reverse(AllFiles),"_"))
AllFiles = 4×1 string array
"Phenolic32_Group5" "P1" "Epx2_G3" "Epoxy_105"
upperchars = isstrprop(AllFiles,'upper')
upperchars = 4×1 cell array
{[1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]} {[ 1 0]} {[ 1 0 0 0 0 1 0]} {[ 1 0 0 0 0 0 0 0 0]}
digitchars = isstrprop(AllFiles,'digit')
digitchars = 4×1 cell array
{[0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1]} {[ 0 1]} {[ 0 0 0 1 0 0 1]} {[ 0 0 0 0 0 0 1 1 1]}
AllFiles = arrayfun(@(a,b,c)(string(a{1}(find(b{:} | c{:})))),cellstr(AllFiles),upperchars,digitchars)
AllFiles = 4×1 string array
"P32G5" "P1" "E2G3" "E105"
IDK, maybe regexp will be better/easier (I've never been able to get my head wrapped around regular expressions and patterns).
...I feel bad, because in the time you've developed this solution I also managed to develop the appropriate regexp for the Phenolic and Epoxy groups, and am now going figuring our how to fuse the two resulting arrays.

Sign in to comment.

 Accepted Answer

S = [...
"textIdontCareAbout_Phenolic32_Group5_textIdontCareAbout"
"textIdontCareAbout_P1_textIdontCareAbout"
"textIdontCareAbout_Epx2_G3_textIdontCareAbout"
"textIdontCareAbout_Epoxy_105_textIdontCareAbout"];
T = regexp(S,'_.+_','match','once');
T = regexprep(T,'[^A-Z\d]','')
T = 4×1 string array
"P32G5" "P1" "E2G3" "E105"

3 Comments

So, as I noted in the comments (realizing I should've gone and edited the original question to include this), that "textIdontCareAbout" includes both letter/number pairings and underscores (which are used as whitespace characters). The following expression captures all the text I'm interested in:
AllFiles = [...
"textIdontCareAbout_Phenolic32_Group5_textIdontCareAbout"
"textIdontCareAbout_P1_textIdontCareAbout"
"textIdontCareAbout_Epx2_G3_textIdontCareAbout"
"textIdontCareAbout_Epoxy_105_textIdontCareAbout"];
SingleExpression = {'(E(poxy|px)?|P(hen(olic)?)?)(_)?\d{1,3}(_G(rp|roup)?(_)?\d{1,2})?'};
temp = regexpi(AllFiles,SingleExpression,'match')
temp = 4×1 cell array
{["Phenolic32_Group5"]} {["P1" ]} {["Epx2_G3" ]} {["Epoxy_105" ]}
However when trying to run a second invocation of regexp on in resulting array temp, MatLab threw the fault
temp2 = regexprep(temp,'[^A-Z\d]','')
Error using regexprep
All cells must be char row vectors.
The solution to the above was the have an intermediate cellstr operation on temp:
temp2 = cellstr(temp);
temp3 = regexprep(temp2,'[^A-Z\d]','')
Why are you nesting this character vector in a superfluous scalar cell array?:
SingleExpression = {'(E(poxy|px)?|P(hen(olic)?)?)(_)?\d{1,3}(_G(rp|roup)?(_)?\d{1,2})?'};
"However when trying to run a second invocation of regexp on in resulting array temp, MatLab threw the fault... The solution to the above was the have an intermediate cellstr operation on temp:"
The error occurs because you did not use the ONCE option, as shown in my answer, so your code adds an extra layer of nested cell arrays. Rather than adding extra commands (e.g. CELLSTR) the simple and efficient solution is to specify the ONCE option, just as I showed you:
temp = regexpi(AllFiles,SingleExpression,'match','once')
% ^^^^^^ simply specify this
The cell brackets {} are because I forgot I don't need them for string arrays. And I've taken your direction and added the 'once' option to the regexpi call. Thank you for your help.

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!