1

I have a nested list below.

{{{0.,0.,1.},1.},{{0.,0.1,0.9},1.},{{0.,0.2,0.8},1.},{{0.,0.3,0.7},1.},{{0.,0.4,0.6},1.},{{0.,0.5,0.5},1.},{{0.,0.6,0.4},1.},{{0.,0.7,0.3},1.},{{0.,0.8,0.2},1.},{{0.,0.9,0.1},1.},{{0.,1.,0.},1.},{{0.1,0.,0.9},68.6},{{0.1,0.1,0.8},68.6},{{0.1,0.2,0.7},68.6},{{0.1,0.3,0.6},68.6},{{0.1,0.4,0.5},68.6},{{0.1,0.5,0.4},68.6},{{0.1,0.6,0.3},68.6},{{0.1,0.7,0.2},68.6},{{0.1,0.8,0.1},68.6},{{0.1,0.9,0.},68.6},{{0.2,0.,0.8},136.2},{{0.2,0.1,0.7},136.2},{{0.2,0.2,0.6},136.2},{{0.2,0.3,0.5},136.2},{{0.2,0.4,0.4},136.2},{{0.2,0.5,0.3},136.2},{{0.2,0.6,0.2},136.2},{{0.2,0.7,0.1},136.2},{{0.2,0.8,0.},136.2},{{0.3,0.,0.7},203.8},{{0.3,0.1,0.6},203.8},{{0.3,0.2,0.5},203.8},{{0.3,0.3,0.4},203.8},{{0.3,0.4,0.3},203.8},{{0.3,0.5,0.2},203.8},{{0.3,0.6,0.1},203.8},{{0.3,0.7,0.},203.8},{{0.4,0.,0.6},271.4},{{0.4,0.1,0.5},271.4},{{0.4,0.2,0.4},271.4},{{0.4,0.3,0.3},271.4},{{0.4,0.4,0.2},271.4},{{0.4,0.5,0.1},271.4},{{0.4,0.6,0.},271.4},{{0.5,0.,0.5},339.},{{0.5,0.1,0.4},339.},{{0.5,0.2,0.3},339.},{{0.5,0.3,0.2},339.},{{0.5,0.4,0.1},339.},{{0.5,0.5,0.},339.},{{0.6,0.,0.4},406.6},{{0.6,0.1,0.3},406.6},{{0.6,0.2,0.2},406.6},{{0.6,0.3,0.1},406.6},{{0.6,0.4,0.},406.6},{{0.7,0.,0.3},474.2},{{0.7,0.1,0.2},474.2},{{0.7,0.2,0.1},474.2},{{0.7,0.3,0.},474.2},{{0.8,0.,0.2},541.8},{{0.8,0.1,0.1},541.8},{{0.8,0.2,0.},541.8},{{0.9,0.,0.1},609.4},{{0.9,0.1,0.},609.4},{{1.,0.,0.},677.}}

I want to split it into several lists if the second elements are same like below.

{{{0., 0., 1.}, 1.}, {{0., 0.1, 0.9}, 1.}, {{0., 0.2, 0.8},1.}, {{0., 0.3, 0.7}, 1.}, {{0., 0.4, 0.6}, 1.}, {{0., 0.5, 0.5},1.}, {{0., 0.6, 0.4}, 1.}, {{0., 0.7, 0.3}, 1.}, {{0., 0.8, 0.2},1.}, {{0., 0.9, 0.1}, 1.}, {{0., 1., 0.}, 1.}}


{{{0.1, 0., 0.9}, 68.6}, {{0.1, 0.1, 0.8}, 68.6}, {{0.1, 0.2, 0.7},68.6},{{0.1, 0.3, 0.6}, 68.6}, {{0.1, 0.4, 0.5},68.6},{{0.1, 0.5, 0.4}, 68.6},{{0.1, 0.6, 0.3},68.6}, {{0.1, 0.7, 0.2}, 68.6}, {{0.1, 0.8, 0.1},68.6},{{0.1, 0.9, 0.}, 68.6}}



{{{0.9, 0., 0.1}, 609.4}, {{0.9, 0.1, 0.}, 609.4}}

{{{1., 0., 0.}, 677.}}

I have tried Cases, Split, Part without success. Your help is greatly appreciated.

Thank you in advance.

kglr
  • 394,356
  • 18
  • 477
  • 896
yaykhel
  • 171
  • 9

3 Answers3

2

Based on my intervals from Find subsequences of consecutive integers inside a list:

mySplit[a_List, pos___] :=
  Take[a, #] & /@ ({Prepend[# + 1, 1], Append[#, -1]}\[Transpose]) &@
    SparseArray[ Differences @ a[[All, pos]] ]["AdjacencyLists"]

This is faster than SplitBy:

dat = (* your expression *)

SplitBy[dat, #[[2]] &] === mySplit[dat, 2]

big = Join @@ Table[dat, {50}];
SplitBy[big, #[[2]] &] // RepeatedTiming // First
mySplit[big, 2]        // RepeatedTiming // First
True

0.00514

0.000579

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
0

Using TakeList in combination with Differences and SparseArray:

ClearAll[splitBy]
splitBy = TakeList[#, Differences @ Join[{0}, 
    SparseArray[Differences @ #[[All, #2]]]["AdjacencyLists"] , {Length @ #}]] &; 

This is twice as fast as Mr.Wizard's mySplit:

big = Join @@ Table[dat, {50}];
r1 = SplitBy[big, #[[2]] &]; // RepeatedTiming // First

0.00572

r2 = mySplit[big, 2]; // RepeatedTiming  // First

0.000778

r3 = splitBy[big, 2]; // RepeatedTiming  // First 

0.000315

r1 == r2 == r3

True

Also,

splitBy2 = TakeList[#, Length /@ Split[#[[All, #2]]]]&
r4 = splitBy2[big, 2]; // RepeatedTiming  // First 

0.000452

r1 == r4

True

kglr
  • 394,356
  • 18
  • 477
  • 896
0

You may use GatherBy and Replace for your matching by pattern requirement.

For the simpler cases you may be able to find a function like Last or create your own with Function and Part. The below are equivalent.

GatherBy[list, Last]
GatherBy[list, #[[-1]]&]

For the pattern match requirement you may use Replace. For the simple case of Last then;

GatherBy[list, Replace[{_List, n_} :> n]]

Or for parts {1, 1} and {2}

GatherBy[list, Replace[{{n1_, ___}, n2_} :> {n1, n2}]]

and so on.

Hope this helps.

Edmund
  • 42,267
  • 3
  • 51
  • 143