0
$\begingroup$

Consider the following table:

tab = Join[RandomReal[{0, 1}, {2, 2}], RandomReal[{0, 1}, {3, 4}], 
  RandomReal[{0, 1}, {2, 3}]]

Could you please tell me how to obtain the list of its sub-tables that have equal number of columns?

I.e.

listtab = {RandomReal[{0, 1}, {2, 2}],RandomReal[{0, 1}, {2, 3}],RandomReal[{0, 1}, {3, 4}]}
$\endgroup$

1 Answer 1

7
$\begingroup$
SeedRandom[1];
tbl = Join[RandomInteger[5, {2, 2}],
  RandomInteger[5, {3, 4}],
  RandomInteger[5, {2, 3}]]
 {{4, 2}, {4, 0},
  {1, 0, 0, 2}, {0, 0, 3, 5}, {2, 0, 3, 4}, 
  {4, 1, 3}, {3, 4, 1}}

You can use SplitBy

SplitBy[tbl, Length]
 {{{4, 2}, {4, 0}}, 
  {{1, 0, 0, 2}, {0, 0, 3, 5}, {2, 0, 3, 4}},
  {{4, 1,3}, {3, 4, 1}}}

If the input is not already sorted by length as in

SeedRandom[1];
tbl2 = RandomSample[tbl]
{{3, 4, 1}, {2, 0, 3, 4}, {1, 0, 0, 2}, {4, 1, 3}, 
 {4, 2}, {0, 0, 3, 5}, {4, 0}}

you can sort it before applying SplitBy

SplitBy[SortBy[{Length}]@tbl2, Length]
 {{{4, 2}, {4, 0}}, 
 {{3, 4, 1}, {4, 1, 3}}, 
 {{2, 0, 3, 4}, {1, 0, 0, 2}, {0, 0, 3, 5}}}

If the output need not be sorted, you can also use GatherBy:

GatherBy[tbl2, Length]
 {{{3, 4, 1}, {4, 1, 3}}, 
  {{2, 0, 3, 4}, {1, 0, 0, 2}, {0, 0, 3, 5}}, 
  {{4, 2}, {4, 0}}}

Alternatively, you can use GroupBy

Values @ GroupBy[Length] @ tbl2
 {{{3, 4, 1}, {4, 1, 3}}, 
  {{2, 0, 3, 4}, {1, 0, 0, 2}, {0, 0, 3, 5}}, 
  {{4, 2}, {4, 0}}}
$\endgroup$
3
  • $\begingroup$ Thanks! When applying SplitBy to the table Join[RandomReal[{2,2},{2,2}],RandomReal[{2,2},{2,3}],RandomReal[{2,2},{2,2}]], it returns 3 tables instead of 2. Namely, it treats the two 2-column tables separated by the 3-column tables as the tables of different lengths. Could you please tell me how to fix this issue? $\endgroup$ May 29 at 12:17
  • 1
    $\begingroup$ However, if the functionality of GatherBy and GroupBy is the same as the one of SplitBy, then this is not important, as the former do things properly. $\endgroup$ May 29 at 12:18
  • 1
    $\begingroup$ if the input list is not sorted by length, you need sort it first before applying SplitBy, that is, you need to use SplitBy[SortBy[{Length}]@tbl3, Length] . (GatherBy and GroupBy work without pre-sorting) $\endgroup$
    – kglr
    May 29 at 12:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.