1
$\begingroup$

I am trying to generalize the responses kindly provided to my question posted here:

to StringJoin adjacent elements only when the second element begins with a designated character such as "("

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

which would produce:

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

I tried:

SequenceReplace[tes, {strs__?(StringContainsQ@
      CharacterRange["(", "("])} :> StringJoin@strs]

but that just gives Lis

$\endgroup$
2
$\begingroup$

Here is a fast approach using Split:

lis = {"abc", "(def)", "ghi", "jkl"};
StringJoin /@ Split[lis, StringStartsQ[#2, "("] &]
(* {"abc(def)", "ghi", "jkl"} *)

lis = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", 
  "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", 
  "z", "a", "b", "c", "d", "(ef)", "g", "m"};
StringJoin /@ Split[lis, StringStartsQ[#2, "("] &]
(* {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "a", 
"b", "c", "d(ef)", "g", "m"} *)
$\endgroup$
2
$\begingroup$
lis = {"abc", "(def)", "ghi", "jkl"};
SequenceReplace[lis, {a_, strs__?(StringStartsQ@"(")} :> StringJoin@{a, strs}]
(* {"abc(def)", "ghi", "jkl"} *)

lis = {"abc", "(def)", "ghi", "(jkl"};
SequenceReplace[lis, {a_, strs__?(StringStartsQ@"(")} :> StringJoin@{a, strs}]
(* {"abc(def)", "ghi(jkl"} *)
$\endgroup$
  • $\begingroup$ This works on the lis in the above comment, but is relatively slow. Thanks to Alx and Rohit for their help!. $\endgroup$ – Suite401 Sep 17 '19 at 4:14
1
$\begingroup$

The idea is using StringStartsQ with needed symbol, "(" here, applyed to pairs of adjasent elements:

If[StringStartsQ[#2,"("], StringJoin[#1,#2],Sequence@@{#1,#2}]&@@@Partition[lis, 2]

EDIT

Fail was because I tested my answer with initial example only: second element of pair contains "(". Next is more general answer: any element of pair can contain "(" and length of lis can be odd (final edit to reveal both cases of "("):

lis = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", 
"m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", 
"z", "a", "b", "c", "d", "(ef)", "g", "g", "(ef)", "m"}    

If[Or @@ StringStartsQ[#, "("], StringJoin[#], Sequence @@ #] & /@ 
Partition[lis, UpTo@2]

gives

{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", \ "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "a", \ "b", "c", "d", "(ef)g", "g(ef)", "m"}

$\endgroup$
  • $\begingroup$ This is fast, but fails for some reason on the following: lis = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "a", "b", "c", "d", "(ef)", "g"}; $\endgroup$ – Suite401 Sep 17 '19 at 4:14
  • $\begingroup$ I don't get the same output in the second example - the second-to-last entry is (ef)g, not g(ef). I'm not sure how to easily fix that issue with this approach though... $\endgroup$ – Lukas Lang Sep 17 '19 at 7:38
  • $\begingroup$ @Suite401 and Lukas Lang, I edited my answer, I checked different versions of code and copyed wrong part. Now it works for me as I posted: added "(ef)", "g" and "g", "(ef)" cases. $\endgroup$ – Alx Sep 17 '19 at 7:55
  • $\begingroup$ @Alx I'm not sure that answers the question - the goal is to "to StringJoin adjacent elements only when the second element begins with...". I think it should therefore be {..., "c", "d(ef)", "g", "g(ef)", "m"} $\endgroup$ – Lukas Lang Sep 17 '19 at 8:07
  • $\begingroup$ @LukasLang, well I thought OP meant pairs of adjacent elements (my Partition part) and changed answer to meet his example in comment, so with my Partition it has now "(" in first element of pair. Probably I misunderstood the question. $\endgroup$ – Alx Sep 17 '19 at 8:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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