# Slicing multidimensional table

Say I have a multidimensional list created in the following way

 grid=
Table[{i, j+1, k+2}, {i, 0, 1}, {j, 0, 1}, {k, 0, 1}]

grid={{{{0, 1, 2}, {0, 1, 3}}, {{0, 2, 2}, {0, 2, 3}}},
{{{1, 1, 2}, {1, 1, 3}}, {{1, 2, 2}, {1, 2, 3}}}}

How can I keep a 2-dimensional slice of this 3-dimensional table, or in general, a 2-dimensional slice of an n-dimensional table?. Say I would like to obtain the array for which the second quantity has the value of 1, i.e.

dim=2; (* The dimension I want to eliminate *)
value=1;
out=f[grid,dim,value]

out={{{0, 2}, {0, 3}}, {{1, 2}, {1, 3}}}

I have worked out a rudimentary way of taking 1-D slices from 2-D sets of data, but nothing I have tried works for >2-dimensional tables.

Thank you very much.

• Part[] in conjunction with the specification All ought to be useful. BTW, out is still a 3D array. May 6, 2015 at 15:17
• Yes, that is the piece I have obtained right, when using Part[grid, All, 2, All] gives me the output I want but still with the column that I want to get rid of, and the problem I am facing is to eliminate that second column. Additionally, I am aware that the output is a 3D array, since I need sort of a "2D array for which each element is a two-coordinate vector".
– Alex
May 6, 2015 at 15:28
• @pepeperez You really need to be careful, what you ask for. You have an array of the form a[i, j, k] and you want to take a slice, eliminating the second dimension? That implies getting the array a[i, j0, k] where j0 is a fixed number. What you're being given in the answers is not a 2D slice, but rather a still 3D array where in a[i, j, k] the 3rd dimension k skips over the value 2. May 6, 2015 at 16:42
• @LLlAMnYP let me see if I can be more explicit: my array grid is a 2x2x2 matrix in which each element is a 3-vector. My intention is to choose a particular value of one of the parameters (say, first parameter being 0) and choose all the values vectors, still in matrix form, that satisfy the condition. This gives me a 2x2 matrix in which each element is a 3-vector with 0 as the first value. Finally, I want to eliminate the first value of each vector in this 2x2 matrix, since it is not relevant any more. You mean that this is not what the answer below is doing?
– Alex
May 6, 2015 at 17:26
• By coincidence, it so happens, that all the vectors with 0 as their first element are restricted to a[1, j, k]. Yes, this is what's being done. Otherwise you could end up with a case where the resulting nested list of vectors is 3D. I have an answer coming up. May 6, 2015 at 17:37

grid={{{{0, 1, 2}, {0, 1, 3}}, {{0, 2, 2}, {0, 2, 3}}},
{{{1, 1, 2}, {1, 1, 3}}, {{1, 2, 2}, {1, 2, 3}}}}


A 2x2x2 list of 3-component vectors.

If I understood correctly, pick out, for example, all such vectors, that have 0 as their first component. I am inclined to take a pattern-matching approach.

grid /. Except[{0, _, _}, {_, _, _}] ->
Unevaluated[Sequence[]] //.
{} -> Unevaluated[Sequence[]] //.
{a_List} :> a


First line reads "take grid and replace everything that matches a 3-component vector, except a vector with 0 at the start with..."

Second line: "...a so called vanishing function. Then repeatedly apply the following rule until nothing changes..."

Third line: "...the rule is to replace empty lists with the same vanishing function. Finally repeatedly apply the rule..."

Fourth line: "...of replacing any list that is the only element of a parent list with itself".

{{{0, 1, 2}, {0, 1, 3}}, {{0, 2, 2}, {0, 2, 3}}}

Because otherwise we would get a 1x2x2 grid instead of a 2x2 grid. But if we have a different grid:

grid = {{{{0, 1, 2}, {0, 1, 3}}, {{0, 2, 2}, {0, 2, 3}}},
{{{0, 1, 2}, {1, 1, 3}}, {{1, 2, 2}, {1, 2, 3}}}}


{{{{0, 1, 2}, {0, 1, 3}}, {{0, 2, 2}, {0, 2, 3}}}, {0, 1, 2}}

Not so great. Still a 3D grid, also the last vector is at a different depth than the others. But here we can drop the last of the replacement rules:

grid /.
Except[{0, _, _}, {_, _, _}] -> Unevaluated[Sequence[]] //.
{} -> Unevaluated[Sequence[]]


{{{{0, 1, 2}, {0, 1, 3}}, {{0, 2, 2}, {0, 2, 3}}}, {{{0, 1, 2}}}}

Anyway, whatever the output, a final replacement rule to drop the 0s:

% /. {0, a_, b_} :> {a, b}


{{{{1, 2}, {1, 3}}, {{2, 2}, {2, 3}}}, {{{1, 2}}}}

or with the original grid and result of its processing:

{{{1, 2}, {1, 3}}, {{2, 2}, {2, 3}}}

Update

This is largely guesswork, but the way your grid is structured is suggestive.

There's a great answer somewhere here about using Flatten with a matrix as the second argument.

This command gives all possible usage options that are applicable for your case ordered in a nice way.

MatrixForm /@ First /@ (Flatten[grid, #] & /@ Permutations[{{1}, {2}, {3}}])


The way your grid is structured,

First@Flatten[grid,{{i},{j},{k}}]


returns the four vectors with matching i-th elements, and depending on the order of j and k they are arranged as {{1,2},{3,4}} or {{1,3},{2,4}}.

So you can also try

(First@Flatten[grid,{{i},{j},{k}}])[[All,All,{j,k}]]


e.g.

(First@Flatten[grid, {{1}, {2}, {3}}])[[All, All, {2, 3}]]


{{{1, 2}, {1, 3}}, {{2, 2}, {2, 3}}}

• Yes, I believe this is the answer to my problem. Thank you very much for your help and the time you have deposited.
– Alex
May 6, 2015 at 18:22
• Thanks for the accept, but maybe there's a much better solution to your problem that someone would be now discouraged to post. In fact I have a great idea with Flatten. May 6, 2015 at 18:31
• Probably you want to "unaccept" the answer to encourage people to work on it? I would be happy to do that if you agree, sorry but I am quite new around here.
– Alex
May 6, 2015 at 19:26
• Yeah, that's I meant :-) May 6, 2015 at 19:29
Pick[#[[All, {1, 3}]], #[[All, 2]], 1] & @@@ grid
(* {{{0, 2}, {0, 3}}, {{1, 2}, {1, 3}}} *)


or

(Select[#, #[[2]] == 1 &] & @@@ grid)[[All, All , {1, 3}]]
(* {{{0, 2}, {0, 3}}, {{1, 2}, {1, 3}}} *)


or

Cases[grid, m : {{_, 1, _} ..} :> m[[All, {1, 3}]], {2}]
(* {{{0, 2}, {0, 3}}, {{1, 2}, {1, 3}}} *)


Update: You can also turn the methods above into functions:

pF[g_, keep_, drop_, val_] := Pick[#[[All, keep]], #[[All, drop]], val] & @@@ g

sF[g_, keep_, drop_, val_] := (Select[#, #[[drop]] == val &] & @@@ g)[[All, All, keep]]

cF[g_, keep_, drop_, val_] := Cases[g, m : {RotateRight[{val, _, _}, drop - 1] ..} :>
m[[All, keep]], {2}]


Examples:

pF[grid, {1, 3}, 2, 1]
(* {{{0, 2}, {0, 3}}, {{1, 2}, {1, 3}}} *)

pF[grid, {1, 2}, 3, 3]
(* {{{0, 1}}, {{1, 1}}} *)

• Thank you @kguler for your great answer. Nevertheless, I still have some questions. Say that now I want to obtain the slice for which the first quantity has the value of 0, how should I modify the above codes to do so?
– Alex
May 6, 2015 at 16:11
• pepeperez, does Pick[#[[All, {1, 3}]], #[[All, 1]], 0] & @@@ grid give the desired output? or Pick[#[[All, {2, 3}]], #[[All, 1]], 0] & @@@ grid?
– kglr
May 6, 2015 at 16:17
• Not quite, but almost. The first one gives {{{0, 2}, {0, 3}}, {}}, and the second one, {{{1, 2}, {1, 3}}, {}}, which is the first part of the desired solution, which would be {{{1, 2}, {1, 3}}, {2, 2}, {2, 3}}}
– Alex
May 6, 2015 at 16:35
• peperez, cF[grid, {2, 3}, 1, 0] gives the correct output. I will fix the ones with Pick and Select.
– kglr
May 6, 2015 at 16:47
• kguler, thank you very much again. Indeed, cF gives the correct output for the first two columns, but both cF[grid, {1, 2}, 3, 2] and cF[grid, {1, 2}, 3, 3] give as result {}
– Alex
May 6, 2015 at 17:12