7
$\begingroup$

I have a list of symbols and integers:

 lis  = {a, b, c, 1, d, e, 2, 3, f}

I'd like to delete each integer that is preceded and succeeded by a symbol:

  res = {a, b, c, d, e, 2, 3, f}

SequenceCases[lis, {a__Symbol, _Integer, b__Symbol} -> {a, b}]

...gives

{{a, b, c, d, e}}
$\endgroup$
1
  • $\begingroup$ Take a look at SequenceReplace $\endgroup$
    – Lukas Lang
    Commented May 28, 2018 at 22:03

5 Answers 5

7
$\begingroup$
Flatten[DeleteCases[SplitBy[lis, IntegerQ], {_Integer}]]
SequenceReplace[lis, {a_Symbol, _Integer, b_Symbol} -> Sequence[a, b]]
With[{s = ArrayPad[BlockMap[FreeQ[#, {_Symbol, _Integer, _Symbol}]&, lis, 3, 1], 1, True]}
  Pick[lis,s]]

all give

{a, b, c, d, e, 2, 3, f}

$\endgroup$
1
  • $\begingroup$ Yes, I missed the Sequence[a,b] in the second solution. Thank you. $\endgroup$
    – Suite401
    Commented May 28, 2018 at 23:19
2
$\begingroup$

ListCorrelate can be useful.

lis = {a, b, c, 1, d, e, 2, 3, f};

bin = Boole[IntegerQ /@ lis]

Pick[lis, Unitize[ListCorrelate[{1, 2, 4}, bin, 2] - 2], 1]
{0, 0, 0, 1, 0, 0, 1, 1, 0}

{a, b, c, d, e, 2, 3, f}

This is faster than either of the methods in kglr's answer that I am able to test in version 10.1:

lis = RandomChoice[{a, b, c, 1, d, e, 2, 3, f}, 150000];

With[{bin = Boole[IntegerQ /@ lis]}, 
   Pick[lis, Unitize[ListCorrelate[{1, 2, 4}, bin, 2] - 2], 1]] // 
  Length // RepeatedTiming

Flatten[DeleteCases[SplitBy[lis, IntegerQ], {_Integer}]] // Length // RepeatedTiming

With[{s = ArrayPad[BlockMap[FreeQ[#, {_Symbol, _Integer, _Symbol}] &, lis, 3, 1], 1,
       True]}, Pick[lis, s]] // Length // RepeatedTiming
{0.0556, 127770}

{0.136, 127770}

{0.1642, 127770}

Most of the time is spent on binarizing the list, so with a faster form for that:

With[{bin = Replace[lis, {_Integer -> 1, _ -> 0}, {1}]}, 
   Pick[lis, Unitize[ListCorrelate[{1, 2, 4}, bin, 2] - 2], 1]] // 
  Length // RepeatedTiming
 {0.0219, 127770}
$\endgroup$
2
$\begingroup$
list = {a, b, c, 1, d, e, 2, 3, f, 9, g};

Using SequenceSplit (new in 11.3)

SequenceSplit[list, {a_Symbol, _Integer, b_Symbol} :> {a, b}] // Flatten

{a, b, c, d, e, 2, 3, f, g}

Using SequencePosition (new in 10.1)

SequencePosition[list, {a_Symbol, _Integer, _Symbol}] /. {a_Integer, _} :> {a}

{{3}, {9}}

Delete[%] @ list

{a, b, 1, d, e, 2, 3, 9, g}

$\endgroup$
2
$\begingroup$
lis = {a, b, c, 1, d, e, 2, 3, f, 5, h};

Using ReplaceRepeated:

lis //. {a___, b_Symbol, n_Integer , c_Symbol, d___} :> {a, b, c, d}

(*{a, b, c, d, e, 2, 3, f, h}*)

Or using SequenceCases and DeleteElements:

DeleteElements[#, SequenceCases[#, {a_Symbol, n_Integer, b_Symbol} :> n]] &@lis

(*{a, b, c, d, e, 2, 3, f, h}*)
$\endgroup$
2
$\begingroup$
list = {a, b, c, 1, d, e, 2, 3, f, 5, h};

Using DeleteElements (new in 13.1)

DeleteElements[
 list,
 Cases[Partition[list, 3, 1], {_Symbol, a_?NumberQ, _Symbol} :> a]]

{a, b, c, d, e, 2, 3, f, h}

$\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.