8
$\begingroup$

I have a list:

lis = {"ab", "cde", 2,"rs",3,"tu","v","w",7}

and would like to get the following list:

lis2 = {abcde, 2,rs, 3,tuvw,7}

... with adjacent strings joined and separated by integers.

Any thoughts would be appreciated!

$\endgroup$

8 Answers 8

7
$\begingroup$

If you don't mind code that generates messages, then the following will work:

Quiet[List@@StringJoin[lis],StringJoin::string]

(* {abcde,2,rs,3,tuvw,7} *)
$\endgroup$
1
  • $\begingroup$ Excellent! Thanks $\endgroup$
    – Suite401
    Commented Jan 28, 2017 at 4:06
7
$\begingroup$
List @@ StringExpression @@ lis

{"abcde", 2, "rs", 3, "tuvw", 7}

In version 10 and later versions you can also use SequenceCases with an appropriate pattern:

SequenceCases[lis, {a : Except[_String] ..., b__String, c : Except[_String] ...} :> 
  Sequence[a, StringJoin@b, c]]

{"abcde", 2, "rs", 3, "tuvw", 7}

$\endgroup$
6
$\begingroup$
lis = {"ab", "cde", 2, "rs", 3, "tu", "v", "w", 7};

lis //. {s___, str1_String, str2_String, f___} :>
  {s, StringJoin[str1, str2], f}

(*  {"abcde", 2, "rs", 3, "tuvw", 7}  *)

or

lis //. {s___, str1_String, str2_String, f___} :>
  {s, str1 <> str2, f}
$\endgroup$
5
$\begingroup$

This is a bit elaborate:

If[VectorQ[#, StringQ], StringJoin[#], Sequence @@ #] & /@ SplitBy[lis, StringQ]
   {"abcde", 2, "rs", 3, "tuvw", 7}
$\endgroup$
2
$\begingroup$
SplitBy[lis,NumericQ] /. {{x__String} :> StringJoin[x], {x_?NumericQ} :> x}
$\endgroup$
2
$\begingroup$
list = {"ab", "cde", 2, "rs", 3, "tu", "v", "w", 7};

Using SequenceSplit (new in 11.3)

SequenceSplit[list, a : {_Integer} :> a[[1]]] /. {a__String} :> StringJoin[a]

{"abcde", 2, "rs", 3, "tuvw", 7}

$\endgroup$
2
$\begingroup$

Using SequenceReplace:

list = {"ab", "cde", 2, "rs", 3, "tu", "v", "w", 7};

SequenceReplace[list, {s__String} :> StringJoin[s]]

Result:

{"abcde", 2, "rs", 3, "tuvw", 7}

$\endgroup$
1
  • 1
    $\begingroup$ +1, extremely nice. I didn't know that SequenceReplace would automatically skip the integers like this. $\endgroup$
    – eldo
    Commented Jan 10, 2024 at 19:25
1
$\begingroup$

If we build ConsecutiveQ we can handle the problem as follows:

ConsecutiveQ[list_List] := AllTrue[Differences[list], # == 1 &]

p1 = Flatten[Position[list, _String]];
p2 = Complement[Range[Length@list], p1];
pstr = Transpose /@ List /@ SequenceCases[p1, {__}?ConsecutiveQ];
pnum = Transpose /@ List /@ SequenceCases[p2, {__}?ConsecutiveQ];
strs = Extract[list, #] & /@ pstr;
nums = Extract[list, #] & /@ pnum;

Flatten[Riffle[strs, nums] /. s_ /; MatchQ[s, {__?StringQ}] :> StringJoin@s]

(*{"abcde", 2, "rs", 3, "tuvw", 7}*)

Or using Cases and SplitBy:

SplitBy[list, StringQ]

Cases[%, s_ :> If[MatchQ[s, {__?StringQ}], StringJoin@s, Splice@s]]

(*{"abcde", 2, "rs", 3, "tuvw", 7}*)
$\endgroup$

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.