I sometimes need a function that would remove background of constant elements from an array, which surround a non-background array block. This is an opposite (so not always inverse) action to an ArrayPad
. ArrayCrop
is to ArrayPad
as ImageCrop
to ImagePad
.
- Did I miss a built-in function that allows to do this?
- Can function below be improved?
While you ponder about it, I will share a version I wrote, at least for programming exercise sake. It is based on SparseArray
as it contains all needed information about background. Here is the function:
Clear@ArrayCrop;
ArrayCrop[m_,v_]:=
Module[
{
ar=Most[ArrayRules[SparseArray[m, Automatic, v]]],
corn
},
corn=Map[Min,Transpose[ar[[All,1]]]];
Normal[
SparseArray[
Rule@@@Thread[{
Map[#-corn+1&,ar[[All,1]]],
ar[[All,2]]
}],
Automatic,
v
]
]
]
ArrayCrop[m_]:=ArrayCrop[m,0]
1D case
Automatic removal of $0$:
l = ArrayPad[{x, y, z}, {2, 3}]
ArrayCrop[l]
Out[1]= {0, 0, x, y, z, 0, 0, 0}
Out[2]= {x, y, z}
Specify element to remove:
l = ArrayPad[{x, y, z}, {2, 3}, w]
ArrayCrop[l, w]
Out[1]= {w, w, x, y, z, w, w, w}
Out[2]= {x, y, z}
2D case
Automatic removal of $0$, - note the $0$-corner cases:
m = ArrayPad[{{0, x, 0}, {x, x, x}, {0, x, 0}}, {{1, 2}, {3, 4}}];
MatrixForm[m]
ArrayCrop[m] // MatrixForm
Specify element to remove:
m = ArrayPad[{{w, x, w}, {x, x, x}, {w, x, w}}, {{1, 2}, {3, 4}}, w];
MatrixForm[m]
ArrayCrop[m, w] // MatrixForm
3D case
core = RandomInteger[2, {2, 3, 4}];
pad = ArrayPad[core, {{1, 1}, {1, 1}, {1, 1}}];
AbsoluteTiming[ArrayCrop[pad] === core]
Image3D[#, ImageSize -> 200] & /@ {core, pad, ArrayCrop[pad]}
5D case
core = RandomInteger[9, {10, 20, 30, 40, 50}];
pad = ArrayPad[core, {{1, 1}, {2, 4}, {5, 6}, {7, 8}, {9, 10}}];
AbsoluteTiming[ArrayCrop[pad] === core]
Out[]= {25.0324, True}
Attachments: