11

I'm trying to find a generic way (for arbitrary dimensions) to create a matrix like so

a[1] a[2]

a[3] a[4]

i.e where it is indexed by one number, instead of say Array[a, {2, 2}] which gives

a[1,1] a[2,1]

a[2,1] a[2,2]

I hope you can help!

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Henrik
  • 111
  • 2

9 Answers9

17

Partition[ Array[a, 4], 2] will do it.

In general,

makeMat[n_, m_] := Partition[ Array[a, n*m], m]
Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
6

With a little indexing arithmetic, one can use only Array[] to generate the required matrix:

With[{m = 4, n = 4},
     Array[C[n (#1 - 1) + #2] &, {m, n}]]
   {{C[1], C[2], C[3], C[4]}, {C[5], C[6], C[7], C[8]},
    {C[9], C[10], C[11], C[12]}, {C[13], C[14], C[15], C[16]}}
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
6
matF1 = Partition[# /@ Range[#2 #3], #3] &
matF2 = ArrayReshape[Array[#, Times[##2]], {##2}] & (* thanks: J.M. *)

{matF1[a, 2, 3], matF2[a, 2, 3]}

{ {{a[1], a[2], a[3]}, {a[4], a[5], a[6]}},
{{a[1], a[2], a[3]}, {a[4], a[5], a[6]}}}

matF2[a, 2, 3, 2]

{{{a[1], a[2]}, {a[3], a[4]}, {a[5], a[6]}},
{{a[7], a[8]}, {a[9], a[10]}, {a[11], a[12]}}}

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

Another method,

makeMat[n_, m_] := 
 Map[a, Array[#2 &, {n, m}] + m Range[0, n - 1], {2}]

makeMat[4, 5] // MatrixForm

enter image description here

Jason B.
  • 68,381
  • 3
  • 139
  • 286
3

It's like the opposite of code-golf,

With[
 {n = 3, m = 5},
 mat = ConstantArray[1, {n, m}];
 i = 1;
 For[j = 1, j <= n, j++,
  For[k = 1, k <= m, k++,
   mat[[j, k]] = a[i];
   i++;
   ]
  ];
 ]
mat // MatrixForm

enter image description here

Jason B.
  • 68,381
  • 3
  • 139
  • 286
2
    n = 4;
    lst = Table[a[i], {i, 0, n}]
    A = Partition[lst, n/2] // MatrixForm

    a[1]    a[2]
    a[3]    a[4]
2

Here is a way that works with arbitrary dimension arrays, without using a dummy counter index:

SparseArray[MapIndexed[# -> a[First@#2] &,
     Sort[Flatten[MapIndexed[ #2 & , #, {-1}],
       Depth[#] - 2]]]] &@Array[0&, {2, 4, 2}] 

enter image description here

even play with SortBy to tweak the ordering:

SparseArray[MapIndexed[# -> a[First@#2] &,
     SortBy[Flatten[MapIndexed[ #2 & , #, {-1}],
       Depth[#] - 2], {#[[1]], #[[3]], #[[2]]} &]]] &@
  Array[0&, {2, 4, 2}]

enter image description here

and a variant that works with arbitrary lists:

ReplacePart[#,
   MapIndexed[# -> a[First@#2] &, 
    Sort[Position[#, x_ /; AtomQ[x], Heads -> False]]]] &@
 {{0, {0, 0, 0}}, {0, 0, {0, 0}}}

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

george2079
  • 38,913
  • 1
  • 43
  • 110
1

Here's another take (although I would have actually done it Szabolcs's way).

mat = {{f, "x"}, {1, Sin[23]}}
Module[{i = 1}, Replace[mat, _ :> a[i++], {2}]]
(* {{f, "x"}, {1, Sin[23]}} *)
(* {{a[1], a[2]}, {a[3], a[4]}} *)
march
  • 23,399
  • 2
  • 44
  • 100
1

One more way:

ClearAll@a
Block[{i = 1}, Array[a[i++] &, {3, 4}]] // MatrixForm
faleichik
  • 12,651
  • 8
  • 43
  • 62