I have a string list:

lis = {"abc","def","def ghi","jkl","ghi","jkl"}

I have another string list whose elements contain two members of lis joined together and separated by a space character:

lis2 = {"abc jkl","def ghi ghi","jkl abc"}

I would like to separate each member of lis2 back into its two components that belong to lis:

res = {{"abc","jkl"},{"def ghi","ghi"},{"jkl","abc"}}

As always, thanks for any ideas.

Here is another sample data set that may state the problem more clearly.

newLis = {"Texas State","Ohio","Sam Houston State","Ohio State"}

newLis2 = {{"Texas","State","Ohio","State"},{"Sam","Houston","State","Ohio","State"},{"Ohio","Sam","Houston","State"}}

Each of the three elements of newLis2 needs to be decomposed into two elements which are members of newLis:

newRes = {{"Texas State","Ohio State"},{"Sam Houston State","Ohio State"},{"Ohio","Sam Houston State"}}

*Please see kglr's comment below, he clearly states the problem at (1). It is best not to make the responders have to guess at the questioner's question :/ *

  • 1
    $\begingroup$ StringSplit /@ lis2 is your after? $\endgroup$
    – yode
    Sep 13, 2018 at 2:38
  • $\begingroup$ No, that gives: {{"abc", "jkl"}, {"def", "ghi", "ghi"}, {"jkl", "abc"}} and I'm aiming for {{"abc","jkl"},{"def ghi","ghi"},{"jkl","abc"}} $\endgroup$
    – Suite401
    Sep 13, 2018 at 2:57
  • $\begingroup$ Suite401, updated problem and the original one are very different questions. Maybe you should make it explicit that the question is a two-part one: (1) Split the strings in input list so that the resulting strings match the ones in a reference list (lis) , and (2) reorganize and StringJoin a list of strings so that the resulting strings match the ones in the references list (lis). $\endgroup$
    – kglr
    Sep 13, 2018 at 5:30
  • $\begingroup$ Yes I agree, kglr - thank you for clarifying. This is exactly what I am trying to do. $\endgroup$
    – Suite401
    Sep 13, 2018 at 5:46
  • $\begingroup$ @kglr yes, the task with the second data sample is what you describe at (1) in your comment. Thank you all for your patience and advice. $\endgroup$
    – Suite401
    Sep 13, 2018 at 5:53

3 Answers 3

alternatives = Apply[Alternatives] @ Reverse @ SortBy[StringLength] @ newLis

StringCases[alternatives] /@  StringRiffle /@ newLis2
"Sam Houston State" | "Texas State" | "Ohio State" | "Ohio" 

{{"Texas State", "Ohio State"}, 
 {"Sam Houston State", "Ohio State"}, 
 {"Ohio", "Sam Houston State"}

Reverse sort is done to make the longes cases more imprtant. E.g. to match Ohio State rather than single Ohio.

  • $\begingroup$ Thank you all for your responses. @Kuba your solution fails on my data set, but if I replace StringCases[alternatives] /@ StringRiffle /@ newLis2 with StringCases[alternatives] /@ StringRiffle /@ newLis2[1] it succeeds. I'll call that a win :) $\endgroup$
    – Suite401
    Sep 13, 2018 at 21:31


StringReplace[lis2,   a__ ~~ " " ~~  b__ /;
   (And @@ (Or @@ StringMatchQ[lis, #]& /@ {a, b})) :> {a,b}] /.
  StringExpression -> Identity

{{"abc", "jkl"}, {"def ghi", "ghi"}, {"jkl", "abc"}}

StringReplace[lis2,  StartOfString ~~ a : Alternatives @@ lis ~~ 
    " " ~~ b : Alternatives @@ lis ~~ EndOfString :> {a, b}] /. 
 StringExpression -> Identity  

{{"abc", "jkl"}, {"def ghi", "ghi"}, {"jkl", "abc"}}


DeleteCases[SequenceAlignment[#, StringJoin @ 
  Riffle[PadRight[lis, 2 Length@lis, "Periodic"], "/"]], _List |  " "] & /@ lis2

{{"abc", "jkl"}, {"def ghi", "ghi"}, {"jkl", "abc"}}

  • $\begingroup$ When I use kglr's second suggestion on the new sample data set, I get the following error message: StringReplace::strse: String or list of strings expected at position 1 in StringReplace[{{Texas,State,Ohio,State},{Sam,Houston,State,Ohio,State},{Ohio,Sam,Houston,State}},StartOfString~~a:Texas State|Ohio|Sam Houston State|Ohio State~~ ~~b:Texas State|Ohio|Sam Houston State|Ohio State~~EndOfString:>{a,b}]. $\endgroup$
    – Suite401
    Sep 13, 2018 at 5:27
  • $\begingroup$ @Suite401, just saw your update. This one is not intended to work for your updated problem. Please see my comment below your question. $\endgroup$
    – kglr
    Sep 13, 2018 at 5:31

Use StringSplit at first and then deal with the special case

If[Length[#] == 3, {StringRiffle[#[[;; 2]]], #[[3]]}, #] & /@ StringSplit[lis2]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.