16
$\begingroup$

If there is a matrix with some of its rows equal to zero: (its zero rows are randomly distributed and does not have an ordered arrangement): same as:

m={{1,2,I},{0,0,0},{I,I,3},{2,6,I},{0,0,0},{0,0,0},{1,6,4},{0,0,0},{1,4,5}}

How can I have a mm matrix without any zero rows and all its rows are m's rows

mm={{1,2,I},{I,I,3},{2,6,I},{1,6,4},{1,4,5}}
$\endgroup$
6
  • 4
    $\begingroup$ Cases[m, Except@{0 ..}] seems the most natural way to me, but probably not the most efficient $\endgroup$ Commented Aug 6, 2015 at 11:50
  • 3
    $\begingroup$ I expect some variation of Select[m, Norm[#] > 0&] to perform better but I haven't tested it. $\endgroup$
    – Szabolcs
    Commented Aug 6, 2015 at 12:01
  • $\begingroup$ Ok, thanks, Both of them work well. $\endgroup$ Commented Aug 6, 2015 at 12:08
  • 5
    $\begingroup$ DeleteCases[m, {0 ..}] should work. $\endgroup$ Commented Aug 6, 2015 at 12:21
  • 1
    $\begingroup$ m /. {0 ..} -> Sequence[] $\endgroup$ Commented Aug 6, 2015 at 17:11

10 Answers 10

17
$\begingroup$

You could use:

Select[m,#!={0,0,0}&]

Where #!={0,0,0}& is a pure function that returns True for any list not equal to the list of three 0's.

$\endgroup$
3
  • $\begingroup$ In which case, you should accept it by clicking the tick-mark next to the upvote arrows. $\endgroup$ Commented Aug 6, 2015 at 12:13
  • $\begingroup$ Yes, I know for accepting an answer, but I have heard not soon accepting an answer. Because of existing a time to others for present their answers. $\endgroup$ Commented Aug 6, 2015 at 12:48
  • 1
    $\begingroup$ @JohMcGee - A more general form using Select would be Select[m, FreeQ[#, {0 ..}] &] $\endgroup$
    – Bob Hanlon
    Commented Aug 6, 2015 at 14:02
9
$\begingroup$

This s/b considerably faster for large cases:

#[[Union[SparseArray[#]["NonzeroPositions"][[All, 1]]]]] &@array

and this is even faster:

Replace[#, ConstantArray[0, Length@#[[1]]] -> Sequence[], {1}] &@array

and about the same as latter:

DeleteCases[#, ConstantArray[0, Length@#[[1]]]]&@array
$\endgroup$
7
$\begingroup$

Try this:

m = {{1, 2, I}, {0, 0, 0}, {I, I, 3}, {2, 6, I}, {0, 0, 0}, {0, 0, 
0}, {1, 6, 4}, {0, 0, 0}, {1, 4, 5}};

DeleteCases[m, {0 ..}, Infinity]

$\left( \begin{array}{ccc} 1 & 2 & i \\ i & i & 3 \\ 2 & 6 & i \\ 1 & 6 & 4 \\ 1 & 4 & 5 \\ \end{array} \right)$

$\endgroup$
6
$\begingroup$

A method that should go well with purely numerical matrices (at least when m has significantly fewer columns than rows) is

Pick[m, Unitize[Abs[m].ConstantArray[1., cols]], 1]

It vectorizes the row checks and does not unpack PackedArrays.

$\endgroup$
4
$\begingroup$
Delete[m, Position[m, ConstantArray[0, Length[First[m]]], {1}]]

Or just

Delete[m, Position[m, {0 ..}, {1}]]
$\endgroup$
3
$\begingroup$
m = {{1, 2, I}, {0}, {I, I, 3}, {2, 6, I}, {0, 0, 0}, {0, 0, 0, 0}, {1, 6, 4}, {0, 0, 0}, {1, 4, 5}};

Using SequenceSplit (new in 11.3)

Join @@ SequenceSplit[m, {{0 ..}}]

{{1, 2, I}, {I, I, 3}, {2, 6, I}, {1, 6, 4}, {1, 4, 5}}

$\endgroup$
3
$\begingroup$

Using ReplaceAll and ContainsOnly:

m = {{1, 2, I}, {0, 0, 0}, {I, I, 3},
    {2, 6, I}, {0, 0, 0}, {0, 0, 0}, 
    {1, 6, 4}, {0, 0, 0}, {1, 4, 5}};
mm = {{1, 2, I}, {I, I, 3}, {2, 6, I}, {1, 6, 4}, {1, 4, 5}};

(m /. x_List /; ContainsOnly[x, {0}] :> Nothing) === mm

(*True*)

Or using ZeroArrayQ:

(m /. x_ /; LinearAlgebra`Private`ZeroArrayQ[x] :> Nothing) === mm

(*True*)
$\endgroup$
3
$\begingroup$

I am adding some contributions. As far as I checked there's no overlap with the suggestions so far. If someone spots something, I would appreciate a comment and I will remove the duplicate.

I am grabbing from @E. Chan-López

m = {{1, 2, I}, {0, 0, 0}, {I, I, 3}, {2, 6, I}, {0, 0, 0}, {0, 0, 
    0}, {1, 6, 4}, {0, 0, 0}, {1, 4, 5}};
mm = {{1, 2, I}, {I, I, 3}, {2, 6, I}, {1, 6, 4}, {1, 4, 5}};

All of the following return True

DeleteElements[m, {0 ..} :> Infinity];
mm === %
m //. {0 ..} :> Unevaluated[## &[]];
mm === %
m //. {0 ..} -> Sequence[];
mm === %
m //. {0 ..} :> Nothing;
mm === %
Delete[Position[{0 ..}]@m]@m;
mm === %
Select[#, UnequalTo[0]] & /@ m //. {} :> Nothing;
mm === %
Cases[m, Except@{0 ..}];
mm === %
Select[m, x |-> FreeQ[x, {0 ..}]];
mm == %
Pick[m, Total /@ Unitize@m, Except[0 | _List]]
mm == %

Edit I am adding this variant which was suggested by the fellow 10-fold ways @ E. Chan-López in the comments

Pick[m, ! MatchQ[#, {0 ..}] & /@ m]
$\endgroup$
2
  • 1
    $\begingroup$ An alternative using Pick: Pick[m, ! MatchQ[#, {0 ..}] & /@ m] :-) $\endgroup$ Commented Dec 28, 2023 at 6:03
  • 1
    $\begingroup$ @E.Chan-López thanks a lot mate :-) Updated $\endgroup$
    – bmf
    Commented Dec 28, 2023 at 13:52
1
$\begingroup$

Using DiscreteDelta:

m = {{1, 2, I}, {0, 0, 0}, {I, I, 3}, {2, 6, I}, {0, 0, 0}, {0, 0, 
    0}, {1, 6, 4}, {0, 0, 0}, {1, 4, 5}};

Pick[m, DiscreteDelta @@@ m, 0]

or

Select[EqualTo[0]@*Apply[DiscreteDelta]][m]

Result:

{{1, 2, I}, {I, I, 3}, {2, 6, I}, {1, 6, 4}, {1, 4, 5}}

$\endgroup$
2
  • 1
    $\begingroup$ +1 - I didn't even know this function :) $\endgroup$
    – eldo
    Commented Feb 19 at 13:33
  • $\begingroup$ Also explore the KroneckerDelta. @eldo $\endgroup$
    – Syed
    Commented Feb 19 at 13:37
0
$\begingroup$

And if you want to delete cases where a certain column is zero, say the last column, this works:

Select[m,#!={#,#,0}&]
$\endgroup$
1
  • 2
    $\begingroup$ First of all, this is not the point in this topic, you can find an appropriate one and add the answer there. Secondly, this is very hairy, such function # != {#, #, 0} &@{1, 1, 0} is left unevaluated. $\endgroup$
    – Kuba
    Commented Apr 4, 2017 at 8:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.