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$
  • $\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$ – J. M.'s discontentment Apr 26 at 14:07
  • $\begingroup$ @J.M. Oh, sorry:) I've fixed it. $\endgroup$ – Andeanlll Apr 26 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$ – Marius Ladegård Meyer Apr 26 at 20:28
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}} *)
| improve this answer | |
$\endgroup$
  • $\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 at 19:55
4
$\begingroup$
SortBy[m, {Count[#, Null], #[[2]]} &]

(*    {{0, 0}, {1, 0}, {0, 1}, {Null, 0}, {1, Null}, {Null, Null}}    *)
| improve this answer | |
$\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}}
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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