5
$\begingroup$

I have a sequence given below:

seq = {{1, 2}, {2, 1}, {2, 2}, {3, 2}, {3, 4}, {4, 2}, {5, 1}, {6,2},
{7, 3}, {8, 4}, {9, 2}, {10, 2}, {10, 3}, {10, 4}, {10,5}, {11, 2}}

I split the list according to the first element

splitlist = SplitBy[seq, First]
{{{1, 2}}, {{2, 1}, {2, 2}}, {{3, 2}, {3, 4}}, {{4, 2}}, {{5,1}},
{{6, 2}}, {{7, 3}}, {{8, 4}}, {{9, 2}}, {{10, 2}, {10,3}, {10, 4}, {10, 5}}, {{11, 2}}}

then decreasing the brackets by 1

splitlist //. {x_} :> x

{{1, 2}, {{2, 1}, {2, 2}}, {{3, 2}, {3, 4}}, {4, 2}, {5, 1}, {6,2}, {7, 3},
{8, 4}, {9,2}, {{10, 2}, {10, 3}, {10, 4}, {10, 5}}, {11, 2}}

Now i wish to find a repeated rule (//.) such that i can group all the consecutive lists of 2 elements together into a single list i.e. {... {{4, 2}, {5, 1}, {6,2}, {7, 3},{8, 4}, {9,2}} ....}

{{1, 2}, {{2, 1}, {2, 2}}, {{3, 2}, {3, 4}}, 

{{4, 2}, {5, 1}, {6,2}, {7, 3},{8, 4}, {9,2}},

{{10, 2}, {10, 3}, {10, 4}, {10, 5}}, {11, 2}} 

Any pattern that can group sublists of elements 2 when they appear consecutively?

$\endgroup$

3 Answers 3

4
$\begingroup$

So if I understand correctly, you want to group the consecutive pairs ({_Integer, _Integer}) at at the first level. Is that correct? In that case, this should probably do the trick:

FixedPoint[
  Replace[#,
    {x1___, 
     x : Longest @ Repeated[{_Integer, _Integer}, {2, \[Infinity]}], 
     x2___} :> {x1, {x}, x2},
    {0}
  ]&,
  {{1, 2}, {{2, 1}, {2, 2}}, {{3, 2}, {3, 4}}, {4, 2}, {5, 1}, {6, 2},
   {7,3}, {8, 4}, {9, 2}, {{10, 2}, {10, 3}, {10, 4}, {10, 5}}, {11, 2}}
]

If you want to apply this at lower levels, you can change the level spec of the Replace. If you want to find other elements that are not lists (instead of just _Integer), you can go with something like {Except[_List], Except[_List]}

Hope this helps.

$\endgroup$
3
  • $\begingroup$ Thanks. it works for a larger set. I was making a mistake :) $\endgroup$
    – Ali Hashmi
    Commented Oct 21, 2016 at 16:30
  • $\begingroup$ btw, please replace x1__ (two underscores) to x1___ (three underscores) and x2__ to x2___ to take care of end cases because for a list like {{1, 2}, {{2, 1}, {2, 2}}, {{3, 2}, {3, 4}}, {4, 2}, {5, 1}, {6, 2}, {7,3}, {8, 4}, {9, 2}, {{10, 2}, {10, 3}, {10, 4}, {10, 5}}, {11, 2},{12,4}} your current implementation will give trouble $\endgroup$
    – Ali Hashmi
    Commented Oct 21, 2016 at 16:36
  • $\begingroup$ Thanks Ali, you're completely correct. I adapted the answer as such. $\endgroup$ Commented Oct 24, 2016 at 8:36
5
$\begingroup$

One step back to go two steps forward:

Split[splitlist, Length @ #1 == Length @ #2 == 1 &] //. {x_} :> x

{{1, 2}, {{2, 1}, {2, 2}}, {{3, 2}, {3, 4}}, {{4, 2}, {5, 1}, {6, 2}, {7, 3}, {8, 4}, {9, 2}}, {{10, 2}, {10, 3}, {10, 4}, {10, 5}}, {11, 2}}


To use PartitionRagged, for fun:

parts = Length /@ Split[Length /@ splitlist, #1 == #2 == 1 &]

{1, 1, 1, 6, 1, 1}

Internal`PartitionRagged[splitlist, parts] //. {x_} :> x

{{1, 2}, {{2, 1}, {2, 2}}, {{3, 2}, {3, 4}}, {{4, 2}, {5, 1}, {6, 2}, {7, 3}, {8, 4}, {9, 2}}, {{10, 2}, {10, 3}, {10, 4}, {10, 5}}, {11, 2}}

$\endgroup$
0
$\begingroup$
list =
  {{1, 2}, {2, 1}, {2, 2}, {3, 2}, {3, 4}, {4, 2}, {5, 1}, {6, 2}, 
   {7, 3}, {8, 4}, {9, 2}, {10, 2}, {10, 3}, {10, 4}, {10, 5}, {11, 2}};

Flatten single pairs

p = x : {{__?NumberQ}} :> First[x];

Combine single pairs

q = x : {{__?NumberQ} ..} :> x;

Using SequenceReplace (new in 11.3)

SequenceReplace[GatherBy[list, First] /. p, q] /. p

{{1, 2}, {{2, 1}, {2, 2}}, {{3, 2}, {3, 4}}, {{4, 2}, {5, 1}, {6, 2}, {7, 3}, {8, 4}, {9, 2}}, {{10, 2}, {10, 3}, {10, 4}, {10, 5}}, {11, 2}}

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