3
$\begingroup$

It's got to be easy, but I can't come up with a general solution.

m = {{16, 2, 3, 13}, {{5, 11, 10, 8}, {9, 7, 6, 12}}, {4, 14, 15, 1}};

What I'm trying to obtain:

m = {16, 2, 3, 13}, {5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1}};

These 'groups of rows' can show at many places, so FlattenAt solution is not enough. I'd really like to use a Flatten or an ArrayFlatten solution.

$\endgroup$
3
  • $\begingroup$ I recommend you give an example list m that shows FlattenAt[m,1] does not work, rather than describing cases in which it will not work. $\endgroup$ Apr 22, 2015 at 22:08
  • $\begingroup$ You're right. Edited $\endgroup$
    – Literal
    Apr 22, 2015 at 22:09
  • $\begingroup$ Are the end result all same length like example? Then something as simple as Partition[Flatten[m], 4] will be most efficient. $\endgroup$
    – ciao
    Apr 22, 2015 at 22:11

3 Answers 3

3
$\begingroup$

If the "Rows" are all same length (here 4):

m = {{16, 2, 3, 13}, {{5, 11, 10, 8}, {9, 7, 6, 12}}, {4, 14, 15, 1}};

Partition[Flatten[m], 4]

(* {{16, 2, 3, 13}, {5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1}} *)

Will be much more efficient...

$\endgroup$
8
  • $\begingroup$ Ooh that's a nice answer! Thanks ! $\endgroup$
    – Literal
    Apr 22, 2015 at 22:15
  • $\begingroup$ @Literal: Glad to help. Don't forget to pick & check an answer, and vote on all that were useful... $\endgroup$
    – ciao
    Apr 22, 2015 at 22:16
  • $\begingroup$ @rasher Don't forget to vote for this earlier incarnation of your answer: (20340) (not mine) $\endgroup$
    – Mr.Wizard
    Apr 22, 2015 at 23:33
  • $\begingroup$ @Mr.Wizard done $\endgroup$
    – ciao
    Apr 22, 2015 at 23:38
  • $\begingroup$ @ciao What is going on with your account? Please tell me you aren't leaving Stack Exchange? :-( $\endgroup$
    – Mr.Wizard
    Apr 23, 2015 at 17:04
3
$\begingroup$
mat = {{{16, 2, 3, 13}, {5, 11, 10, 8}}, {9, 7, 6, 12}, {4, 14, 15, 1},
       {{a, b, c}, {v, x, y}}};

mat2 = MapAt[## & @@ # &, mat, Position[mat, {{__}, {__}}]]
(* {{16, 2, 3, 13}, {5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1}, 
    {a, b, c}, {v, x, y}} *)

mat3 = FlattenAt[mat, Position[mat, {{__}, {__}}]]
(* {{16, 2, 3, 13}, {5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1}, 
    {a, b, c}, {v, x, y}} *)
$\endgroup$
7
  • $\begingroup$ Ok thanks. I thought it would have been easier to achieve it (involving a single function) $\endgroup$
    – Literal
    Apr 22, 2015 at 22:07
  • $\begingroup$ I swear, BlankNullSequence must have compromising photos of you, as much as you use it ;-) +1 for patterny prettiness! $\endgroup$
    – ciao
    Apr 22, 2015 at 22:17
  • $\begingroup$ thank you @rasher. Source: BlankNullSequence infection :) $\endgroup$
    – kglr
    Apr 22, 2015 at 23:09
  • $\begingroup$ Mr. 70K, please try a little harder to help me find duplicates; I know you have seen this one. You're #2 on the site now and I need all the help I can get! $\endgroup$
    – Mr.Wizard
    Apr 22, 2015 at 23:35
  • $\begingroup$ Heard you @Mr.W. What keywords did you use to get the link (this one)? $\endgroup$
    – kglr
    Apr 23, 2015 at 8:07
1
$\begingroup$

Given:

m = {{16, 2, 3, 13}, {{5, 11, 10, 8}, {9, 7, 6, 12}}, {4, 14, 15, 1}};

We could use Sequence to "unwrap" lists of depth 3:

Apply[Sequence, m, {-3}]

(* {{16, 2, 3, 13}, {5, 11, 10, 8}, {9, 7, 6, 12}, {4, 14, 15, 1}} *)

Equivalently:

Apply[##&, m, {-3}]

Direct replacement of nested lists can work too:

Replace[m, {x:_List...} :> x, {1}]

These approaches will work on variable-length rows:

m2 = {{1, 2}, {{3, 4, 5}, {6, 7, 8}}, {9, 10, 11}, {{12, 13}, {14, 15}, {16}}};

Apply[##&, m2, {-3}]

(* {{1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}, {12, 13}, {14, 15}, {16}} *)

If the nesting is variable-depth, we can use Reap and Sow:

m3 = {{1, 2}, {{3, 4}, {{5, 6}, {7, 8}}}, {{{{9, 10}}, {11, 12}}}};

Scan[Sow, m3, {-2}] // Reap // #[[2, 1]] &

(* {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}} *)
$\endgroup$

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