Given a (large) rectangular array, e.g. (small for example case):
Column[{test, test // MatrixForm}, Left, 2]
(*
{{1, 3, 0, 3, 0}, {1, 3, 0, 3, 3}, {0, 2, 3, 1, 3}, {2, 0, 0, 0, 0},
{2, 0, 2, 3, 1}, {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}}
*)
I need to remove any leading/trailing zeroes from rows, dropping row if all zeroes, e.g. with above the result s/b
(* {{1, 3, 0, 3}, {1, 3, 0, 3, 3}, {2, 3, 1, 3}, {2}, {2, 0, 2, 3, 1}, {1}} *)
I'm using
trim0 = With[{t = DeleteCases[#, ConstantArray[0, Length@#[[1]]]]},
MapIndexed[t[[First@#2, #1[[1]] ;; #1[[-1]]]] &, SparseArray[t]["AdjacencyLists"]]] &;
Might there be a faster method?
N.B.: Currently, I'm working with arrays of non-negative integers, so if that can be used to speed things (above is general)...
Answer
idtz = Internal`DeleteTrailingZeros;
trim0a = With[{t = Reverse/@ idtz/@DeleteCases[#, ConstantArray[0, Length@#[[1]]]]},
Reverse /@ idtz /@ t] &;
trim0b = With[{t = DeleteCases[#, ConstantArray[0, Length@#[[1]]]]},
Fold[idtz@#2@# &, #, {Reverse, Reverse}] & /@ t] &;
Equal @@ (#@test & /@ {trim0, trim0a, trim0b})
(* True *)
Some timings:
n = 5000; m = 5000; k = 1;
testmat = RandomChoice[{k, 1, 1, 1} -> Range[0, 3], {n, m}];
rslt = {0, 0, 0}; i = 1;
First[AbsoluteTiming[rslt[[i++]] = #@testmat ;]] & /@ {trim0, trim0a, trim0b}
(* {1.900441, 1.351605, 0.965583} *)
Equal @@ rslt
(* True *)
n = 5000; m = 5000; k = 5;
(* {1.265648, 1.555662, 1.140635} *)
n = 1000000; m = 10; k = 1;
(* {6.119162, 4.407390, 5.105766} *)
n = 1000000; m = 10; k = 5;
(* {5.770310, 4.532018, 5.306773} *)
Comments
Post a Comment