2
$\begingroup$

I have a $n$ by $2$ matrix that has binary values(0,1) as its entry. For example

m={{1,Null},{Null,0},{Null,Null},{0,0},{1,0},{0,1}}

I want it to be sorted according to a simple rule: 1) place non-empty ones at the top and empty ones at the bottom; 2) if a row has only one non-empty value, the row that has a non-empty value in column 2 places before the row that has a non-empty value in column 1. For example, {Null,0} should be placed before {1,Null}.

So, the final list I want to have should look like:

m_sorted={{0,0},{1,0},{0,1},{Null,0},{1,Null},{Null,Null}}.

How can I do this type of sorting?

$\endgroup$
3
  • $\begingroup$ "{Null, 0} should be placed before {1, Null}" - and yet in your sorted list, you have {1, Null}, {Null, 0}. Do make up your mind. $\endgroup$ Apr 26, 2020 at 14:07
  • $\begingroup$ @J.M. Oh, sorry:) I've fixed it. $\endgroup$
    – Andeanlll
    Apr 26, 2020 at 14:08
  • $\begingroup$ Tip not directly directed at the problem here: if $n$ tends to be large in your use cases, then using Null is going to slow things down compared to using another integer, say, -1. The reason is that Mathematica can "pack" arrays that only contain one type (typically ints or floats). Using Null prevents that. $\endgroup$ Apr 26, 2020 at 20:28

3 Answers 3

3
$\begingroup$

Not very elegant but should do the trick:

  • select the pairs of integers without reordering
  • select the pairs of one integer and one Null and reorder by Null first
  • select the pairs of Nulls
  • join all that

and enjoy.

   process[m_] := Block[{a, b, c},
      a = Select[m, IntegerQ@Total@# &];
      b = SortBy[Last]@Select[m, Count[#, Null] == 1 &];
      c = Select[m, # == {Null, Null} &];
      Flatten[Join[{a, b, c}], 1]]
    process[m]

    (* {{0, 0}, {1, 0}, {0, 1}, {Null, 0}, {1, Null}, {Null, Null}} *)
$\endgroup$
1
  • $\begingroup$ Thank you for the accept but, especially if you are looking for performances, Roman and kglr's answer are probably better. $\endgroup$
    – anderstood
    Apr 27, 2020 at 19:55
4
$\begingroup$
SortBy[m, {Count[#, Null], #[[2]]} &]

(*    {{0, 0}, {1, 0}, {0, 1}, {Null, 0}, {1, Null}, {Null, Null}}    *)
$\endgroup$
3
$\begingroup$
SortBy[{Count[Null], Last}] @ m
{{0, 0}, {1, 0}, {0, 1}, {Null, 0}, {1, Null}, {Null, Null}}

Also

m[[Ordering[Through[{Count[Null], Last}@#] & /@ m]]]
{{0, 0}, {1, 0}, {0, 1}, {Null, 0}, {1, Null}, {Null, Null}}
$\endgroup$

Your Answer

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

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