7
$\begingroup$

I have a list consisting of strings and numbers, from which I need to extract sublists.

lis = {k, a, b, cf, e, 1, c, d, 2, z, d, 3, f, g, z, h, a, q, r, 4, s, 5, z, j, a}

The sublists I need are defined as a sequence of four elements bracketed by "a" and "z", and with adjacent string elements joined to each other:

{a, b, cf, e, 1, c, d, 2, z}  -> {bcfe, 1, cd, 2}

So the desired result is:

res = {{bcfe, 1, cd, 2}, {qr, 4, s, 5}}

Thanks for suggestions!

$\endgroup$

4 Answers 4

6
$\begingroup$
Clear["Global`*"];

lis = {k, a, b, cf, e, 1, c, d, 2, z, d, 3, f, g, z, h, a, q, r, 4, 
   s, 5, z, j, a};

Your lis does not contain any strings

Head /@ lis // Union

(* {Integer, Symbol} *)

DeleteCases[
  lis //. 
   {s___, a, mid___, z, e___} :> {s, SplitBy[{mid}, ! IntegerQ[#] &], 
     e}, _?AtomQ, 1] /. {{i_Integer} :> i, 
  sym : {_Symbol ..} :> StringJoin[ToString /@ sym]}

(* {{"bcfe", 1, "cd", 2}, {"qr", 4, "s", 5}} *)

EDIT: If the list has strings instead of symbols,

lis = {"k", "a", "b", "cf", "e", 1, "c", "d", 2, "z", "d", 3, "f", "g", "z", 
   "h", "a", "q", "r", 4, "s", 5, "z", "j", "a"};

DeleteCases[
  lis //. {s___, "a", mid___, "z", e___} :> 
     {s, SplitBy[{mid}, ! IntegerQ[#] &], e}, _?AtomQ, 1] /. 
      {{i_Integer} :> i, 
       str : {_String ..} :> StringJoin[str]}

(* {{"bcfe", 1, "cd", 2}, {"qr", 4, "s", 5}} *)
$\endgroup$
1
  • $\begingroup$ Thanks Bob for the reply. My error. I meant strings, not symbols in lis = {"k", "a", "b", "cf", "e", 1, "c", "d", 2, "z", "d", 3, "f", "g", "z", "h", "a", "q", "r", 4, "s", 5, "z", "j", "a"}; a revision of your solution would be welcome. $\endgroup$
    – Suite401
    Aug 28 at 4:19
4
$\begingroup$
ClearAll[reShape]
reShape[a_, z_] :=  SequenceCases[#, {a, x : Except[a | z] .., z} :> 
    SequenceReplace[{x}, {s__String} :> StringJoin @ s]] &

Example:

lis = {"k", "a", "b", "cf", "e", 1, "c", "d", 2, "z", "d", 3, "f", 
   "g", "z", "h", "a", "q", "r", 4, "s", 5, "z", "j", "a"};

reShape["a", "z"] @ lis
{{"bcfe", 1, "cd", 2}, {"qr", 4, "s", 5}}
$\endgroup$
3
$\begingroup$
blist = {"k", "a", "b", "cf", "e", 1, "c", "d", 2, "z", "d", 3, "f", 
   "g", "z", "h", "a", "q", "r", 4, "s", 5, "z", "j", "a"};

Define three polymorphic functions with Symbol, Integer, String arguments for list catenation.

Clear[f]
f[k_List /; AllTrue[k, Head[#] == Symbol &]] := 
 StringJoin @@ ToString /@ k
f[k_List /; AllTrue[k, IntegerQ]] := k
f[k_List /; 
   AllTrue[StringJoin @@ Join @@ Characters /@ k, 
    MemberQ[Alphabet[]] &]] := StringJoin @@ Join @@ Characters /@ k

Using SequenceCases:

Map[Flatten, #, {-3}] &@
     Map[f, #, {-2}] &@
   SplitBy[#, IntegerQ] & /@
 SequenceCases[blist
  , {"a", k : Except["z"] .., "z"} :> {k}]

{{"bcfe", 1, "cd", 2}, {"qr", 4, "s", 5}}

$\endgroup$
3
$\begingroup$
lis = {"k", "a", "b", "cf", "e", 1, "c", "d",
   2, "z", "d", 3, "f", "g", "z", "h", "a",
   "q", "r", 4, "s", 5, "z", "j", "a"};

{ap, zp} = Flatten[Position[lis, #]] & /@ {"a", "z"}

sel = DeleteDuplicatesBy[DeleteCases[Function[av, {av + 1,
       SelectFirst[zp, # > av &, 0] - 1}] /@ ap, {_, -1}], Last];

Map[Take[lis, #] &, sel] //.
 {h___, i_String, j_String, k___} :> {h, i <> j, k}

{{"bcfe", 1, "cd", 2}, {"qr", 4, "s", 5}}

$\endgroup$

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.