13

I have a matrix where every item in the matrix has its own brackets that I do not want. How can I remove the brackets around each item?

Here is the matrix shown in both displays

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
C. Tamaro
  • 131
  • 1
  • 3

7 Answers7

14

Wrap the matrix rows with the the Flatten function

M = {{{1}, {2}, {3}, {4}}, {{5}, {6}, {7}, {8}}}

the matrix

To save time you can wrap your whole matrix using: Map[Flatten, <yourmatrix> ]

Map[Flatten,{{{1}, {2}, {3}, {4}}, {{5}, {6}, {7}, {8}}}]

the outermost list contains two elements (the rows). the Map function wraps these elements with the Flatten function

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

In Mathematica this is known as "nested" Lists. Flatten removes all wrappings of the List function until only one remains

To understand what the Map function does: Below is the "manual" approach without the Map function.

{  
 Flatten[{{1}, {2}, {3}, {4}}],

 Flatten[{{5}, {6}, {7}, {7}}]
}

As you are talking to an awesome machine called the Mathematica kernel you don't have to waste time writing things in long hand to make them readable (like you would for a slow-to-understand human reader of an essay or your future self reading your code).

hence Map[Flatten, Matrix] has the terse shorthand form Flatten /@ matrix

mentioned by @garej , @jjc385 and @Mr.Wizard below

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Conor
  • 7,449
  • 1
  • 22
  • 46
  • 1
    As this answer is clearly geared for new users, I think this answer would be somewhat improved by mentioning the syntactic sugar Flatten /@ <matrix>. – jjc385 Feb 08 '16 at 13:18
  • (Is it polite/conventional to delete a comment such as mine above after the edit has been made?) – jjc385 Feb 08 '16 at 14:01
  • @jjc385 I have not observed a specific convention in that regard. The comments can serve as minor credit for the source of an edit, and I don't see anything wrong with that. However since you are mentioned by (nick)name in the answer now the comments seems redundant and I would probably delete it if it where mine. – Mr.Wizard Feb 16 '16 at 13:57
14

Lots of solutions. Time for a benchmark. My own contribution is Part:

m = {{{1}, {2}, {3}}, {{2}, {4}, {6}}};

m[[All, All, 1]];
{{1, 2, 3}, {2, 4, 6}}

Update: I made a complete mess of my earlier attempt at benchmarking. Here is a rewrite.

methods = Hold[Flatten /@ m, ArrayReshape[m, Most@Dimensions@m], 
   ArrayReshape[m, Dimensions[m][[1 ;; 2]]], Flatten[m, {Depth[m] - 1, 1}], 
   Apply[Sequence, m, {2}], Apply[Sequence, m, {-2}], Join @@@ m, m[[All, All, 1]], 
   Catenate /@ m];

names = {"Map[Flatten]", "ArrayReshape 1", "ArrayReshape 2", "Flatten w/ Depth", 
   "Sequence {2}", "Sequence {-2}", "Join", "Part", "Map[Catenate]"};

upk[{x_, y_}] := Table[{ToString[i*j]}, {i, x}, {j, y}];
pkd[{x_, y_}] := RandomReal[1, {x, y, 1}];

tab = 
 Table[
  List @@ First /@ RepeatedTiming /@ methods,
  {fn, {upk, pkd}},
  {shape, {{10, 100000}, {1000, 1000}, {100000, 10}}},
  {m, {fn[shape]}}
 ];

TableForm[
  Append[names] /@ (tab //. {x_List} :> x),
  TableHeadings -> {{"Unpacked", "Packed"}, {{10, 100000}, {1000, 1000}, {100000, 10}}},
  TableSpacing -> {5, 1, 0.5}
]

enter image description here
(Benchmark timings in 10.1.0 under Windows 7 x64.)

It seems that in most instances Part wins, but a few times Catenate edges it out.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • I don't mean to question the infinite wisdom of Mr.Wizard, but as a relatively new user who just spent a few minutes trying to understand this code, I think it would be immensely helpful (and not terribly time consuming) if you somehow paired each column of output for the tests with a description of that test. For example, you could include a line {"Flatten-Map", "ArrayShape-Most", "ArrayShape", "Flatten-Depth","Apply-Sequence","Apply-Sequence-Backward","Join","Part-All"} each of the three sets of output. It might also be helpful to sort somehow, but I can imagine arguing either way. – jjc385 Feb 08 '16 at 13:12
  • I'm sure a wizard like you can work this into the definition of the tests themselves! – jjc385 Feb 08 '16 at 13:13
  • 1
    @jjc385 Sorry, I was just being lazy. Actually really lazy as if the code I copied is actually what I ran the second test is a total mess. Earlier I had a comment "where's my coffee" -- I guess I really needed it! – Mr.Wizard Feb 08 '16 at 14:15
  • 1
    @jjc385 I rewrote the benchmark and got a different result. I hope I got it right this time but I am not certain I am still thinking clearly. Please let me know if you notice any stupid mistakes. – Mr.Wizard Feb 08 '16 at 15:01
  • 1
    It looks good to me, but then again I'm running on 2 hours of sleep and a can of soda at 7am ;)

    By the way, and I'm not suggesting you implement this here, do you know of a slick way to do something like highlighting the elements of a list, with the highlighting color changing based on their values? It would be a good way to instantly see the winner for tests like these. (I admit I ask more out of curiosity than practicality.)

    – jjc385 Feb 08 '16 at 15:43
  • 1
    @Mr.Wizard, would you mind to check this method: Catenate /@ m. It will not beat Part but I'm not sure about other options. – garej Feb 08 '16 at 16:52
  • I get slightly different results with your benchmarking: http://i.stack.imgur.com/MlcPo.png, but in both yours & mine, ArrayReshape has roughly constant timing on 10^6 elements in all three shapes, esp. on packed arrays. Join seems quite different on my system on packed arrays (Mac/Intel i7). – Michael E2 Feb 09 '16 at 04:03
  • @MichaelE2, at my machine Catenate /@ m wins in many categories (Win, i5, 8Gb). – garej Feb 09 '16 at 05:34
  • 1
    @garej Added to benchmark, along with a note of the system I am performing the benchmarking on. – Mr.Wizard Feb 09 '16 at 07:14
  • 2
    @garej What I found interesting was that relative performance seemed to vary by system so much. It's nice to see a new function (Catenate) be an improvement once in a while. My last row is very different: 0.0044, 0.0063, 0.11. Note though that Catenate is not compilable, which is why it loses out to Flatten on longer lists; it also why mapping it unpacks the list (to level 1 only), making further processing less efficient (unless repacked). Join unpacks to level 2; Sequence unpacks the whole array. Not sure why a difference in timing is not reflected on Mr.Wizard's computer. – Michael E2 Feb 09 '16 at 13:52
  • @MichaelE2, I have results similar with yours (on Win machine). Thank you for pointing out the packing issue. – garej Feb 11 '16 at 08:19
10

You can use ArrayReshape. Either

ArrayReshape[mat, Most@Dimensions@mat]

or

ArrayReshape[mat, Dimensions[mat][[1 ;; 2]]]

It will keep a packed array packed, too.

Mathematica graphics

Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • Readers of this answer can find some further discussion of using ArrayReshape to remove unwanted singleton list wrappings, e.g., {a] or {{a, b, c}} in this answer – m_goldberg Aug 02 '16 at 12:51
7

Edit With m = RandomInteger[9, {3, 6, 1}]

Just for completeness:

Catenate /@ m

Just for diversity reasons

Apply[#&, m, {2}]
Apply[Sequence, m, {-2}]
Map[First, m, {2}]

Using @Mr.Wizard code I have updated the benchmark.

enter image description here

@MichaelE2 also noticed in comments that Catenate is not compilable.

garej
  • 4,865
  • 2
  • 19
  • 42
  • 1
    I get similar results, to within a scaling factor for my slow CPU. Interesting that Join is much worse on packed arrays! – Simon Woods Feb 15 '16 at 20:22
  • @SimonWoods, MichaelE2 in a comment says "that Join unpacks to level 2. Sequence unpacks the whole array". He gets similar results. I'm surprized that Catenate behaves so different within packed group. – garej Feb 15 '16 at 21:12
7

You can also Apply Join at level 1 to your list:

m = RandomInteger[9, {2, 4, 1}]

{{{0}, {6}, {7}, {5}}, {{1}, {3}, {8}, {8}}}

Join @@@ m

{{0, 6, 7, 5}, {1, 3, 8, 8}}

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

I suggest Flatten[m, {Depth[m] - 1, 1}], where m is the matrix in question.

For example,

SeedRandom[1]; m = RandomInteger[99, {4, 5, 1}]
{{{80}, {14}, {0}, {67}, {3}}, 
 {{65}, {23}, {97}, {68}, {74}}, 
 {{15},{24}, {4}, {90}, {83}}, 
 {{70}, {1}, {30}, {48}, {25}}}
Flatten[m, {Depth[m] - 1, 1}]
{{80, 14, 0, 67, 3}, 
 {65, 23, 97, 68, 74}, 
 {15, 24, 4, 90, 83}, 
 {70, 1, 30, 48, 25}}
m_goldberg
  • 107,779
  • 16
  • 103
  • 257
2

...and of course, there's always Transpose[]:

Transpose[{{{1}, {2}, {3}}, {{2}, {4}, {6}}}, {2, 3, 1}] // First
   {{1, 2, 3}, {2, 4, 6}}

The Flatten[] equivalent is then

Flatten[{{{1}, {2}, {3}}, {{2}, {4}, {6}}}, {{1}, {3, 2}}]
   {{1, 2, 3}, {2, 4, 6}}
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574