Splitting table text column with multiple delimiters based on parantheses.

12 views (last 30 days)
greenyellow22
greenyellow22 on 26 May 2022
Commented: Stephen23 on 23 Jun 2022 at 8:42
Hey! I have a table with multiple columns and one of them is in text form (called 'Status', for cell examples see below). I would like to split this colum into two based on the parantheses, so that I have one column with the text (e.g. User has collected a REGULAR coin at/ Access to new world) and one with the numbers (e.g. -5.5, 10.9, 90.1).
oldtable.Status =
Player collected a YELLOW coin at (-5.5, 10.9, 90.1)
Access to new world
New world entered
Player collected a GREEN coin at (6.6, 8.7, 74.9)
...
Player collected a GREEN coin at (4.7, 9.7, 71.7)
First, I tried simply the split function and got an error message:
newtable = split(oldtable.Status)
Error using split
Element 2 of the text contains 3 delimiters while the previous elements have 6. All elements must contain the same number of delimiters.
And also tried the multiple delimierts function:
newtable = split(oldtable.Status["("])
Invalid expression. When calling a function or indexing a variable, use parentheses. Otherwise, check for mismatched delimiters.
Thank you in advance! :-)

Accepted Answer

Stephen23
Stephen23 on 27 May 2022
S = ["Player collected a YELLOW coin at (-5.5, 10.9, 90.1)";"Access to new world";"New world entered";"Player collected a GREEN coin at (6.6, 8.7, 74.9)"]
S = 4×1 string array
"Player collected a YELLOW coin at (-5.5, 10.9, 90.1)" "Access to new world" "New world entered" "Player collected a GREEN coin at (6.6, 8.7, 74.9)"
T = regexp(S,'^(.*?)(\(.*\))?$','once','tokens');
T = vertcat(T{:})
T = 4×2 string array
"Player collected a YELLOW coin at " "(-5.5, 10.9, 90.1)" "Access to new world" "" "New world entered" "" "Player collected a GREEN coin at " "(6.6, 8.7, 74.9)"
  4 Comments
Stephen23
Stephen23 on 23 Jun 2022 at 8:42
% '^(.*?)(\(.*\))?$'
% ^ match the start of the string
% ^ ^ define group 1
% ^^^ match any character zero or more times, lazy
% ^ ^ define group 2
% ^^ ^^ match literal parentheses
% ^^ match any character zero or more times, greedy
% ^ make group 2 optional
% ^ match end of the string
The regular expression basically works by trying to match the literal parentheses, and if that fails, the lazy match will catch everything. It expects the parentheses to be at the end of the text.
If you want to obtain and "filter out" the coordinates anwhere in the text, perhaps:
S = ["Player collected a YELLOW coin at (-5.5, 10.9, 90.1)";"Access to new world";"New world entered";"Player collected a GREEN coin at (6.6, 8.7, 74.9)";"Player took 1 damage at (86.8, 59.9, -22.6) and was knocked back with booster: 14 away from enemy: True"]
S = 5×1 string array
"Player collected a YELLOW coin at (-5.5, 10.9, 90.1)" "Access to new world" "New world entered" "Player collected a GREEN coin at (6.6, 8.7, 74.9)" "Player took 1 damage at (86.8, 59.9, -22.6) and was knocked back with booster: 14 away from enemy: True"
R = '([^\(]+)(\(.+\))?(.*)';
T = regexp(S,R,'tokens','once');
T = vertcat(T{:})
T = 5×3 string array
"Player collected a YELLOW coin at " "(-5.5, 10.9, 90.1)" "" "Access to new world" "" "" "New world entered" "" "" "Player collected a GREEN coin at " "(6.6, 8.7, 74.9)" "" "Player took 1 damage at " "(86.8, 59.9, -22.6)" " and was knocked back with booster: 14 away from enemy: True"

Sign in to comment.

More Answers (1)

dpb
dpb on 27 May 2022
A rudeness about way the string functions are implemented -- they won't return variable numbers of elements that would be extremely handy -- without more exotic things like regexp, the workaround is something like
>> Status =["Player collected a YELLOW coin at (-5.5, 10.9, 90.1)"
"Access to new world "
"New world entered"
"Player collected a GREEN coin at (6.6, 8.7, 74.9)"];
>> ix=contains(Status,'(');
>> numStr(ix,1)=extractBetween(Status(ix),'(',')')
numStr =
4×4 string array
"-5.5, 10.9, 90.1" <missing> <missing> "6.6, 8.7, 74.9"
<missing> <missing> <missing> <missing>
<missing> <missing> <missing> <missing>
"6.6, 8.7, 74.9" <missing> <missing> <missing>
>>
The above just pasted in your displayed text and made it into something readable the simplest way possible -- each line is an array element. To duplicate your exact case would need to know the precise format of the input, but the above is how to work with the higher-leve builtin functions to get around their penchant to have everything excessively uniform.

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!