If you want to check every element including the indices out front of each 2 x 2 matrix, you could use:
Select[list, AllTrue[Flatten[#], NonNegative] &]
Using NonNegative
will catch cases where the value is zero since NonNegative[0]
evaluates to True
. If you don't want zero to be included, you can use Positive
like in Omrie Ovdat's answer.
This will return all rows where the condition is met. If you just want the 2 x 2 matrices and not the values in front, there are a number of options including:
Select[list, AllTrue[Flatten[#], NonNegative] &][[All, 4]]
or
Select[list, AllTrue[Flatten[#[[4]]], NonNegative] &]
though this last one will only test the 2 x 2 matrix itself and won't test the numbers in front.
Also, keep in mind that while Grid
is nice for display purposes, Grid
, MatrixForm
, TableForm
, and friends don't behave the same as the actual list of lists. So if you have newlist = Grid[list]
, the functions above won't work on newlist
.
Clarifications:
Select
looks through each part of the top-most list, one-at-a-time. So to start with, it would extract the very first row of your grid. It then feeds that single row to the second part of the Select
function (that would be AllTrue[Flatten[#], NonNegative] &
).
The &
tells Mathematica to feed that row into the placeholder (#
) to its left. So the #
is replaced by that entire first row.
Now we have something like Flatten[{1, 2, 2, {{0.45, -12}, {0.399896 - 0.547998*i, 7}}}]
. Flatten
takes a list of lists and turns it into a single list. The output of this part would be {1, 2, 2, 0.45, -12, 0.399896 - 0.547998*i, 7}
in this case. The reason for doing this is because AllTrue
in the next step gives a list of lists as the output if I don't use Flatten
when I just want a single True
or False
as the output.
Then, AllTrue
is designed to take each element of this list and test it with the function NonNegative
. Essentially the same thing happens here as with the #
/&
pair earlier. Each element of the flattened list is tested in turn by being fed into NonNegative
. I could have also wrote NonNegative[#]&
, but it doesn't need the extra characters in this case so I didn't use them.
NonNegative
checks any number to make sure it is non-negative. The definition in the documentation says:
NonNegative[x] gives False if x is manifestly a negative or complex numerical quantity. Otherwise, it remains unevaluated.
This means it will give True
for non-negative real numbers. 0 is not negative, so it is included here. If you don't want to include 0, you can use Positive
. Positive[0]
gives False
. Keep in mind that if you have something other than a number, nothing at all will happen. So if one of your elements happens to be a string ("Hello World") or a variable (x
), you'll just get NonNegative["Hello World"]
or NonNegative[x]
as output since it cannot evaluate the input.
Note:
I just realized that you have lower case i in your numbers. In fact, NonNegative[list[[1, 4, 2, 1]]]
gives NonNegative[0.399896 -0.547998 i]
. This is because Mathematica does not recognize the "i" as indicating a complex number. In Mathematica, it should be a capital I. The code still works because Select
chooses only those that evaluate to True
. Anything that evaluates to False
or in this case NonNegative[0.399896 -0.547998 i]
is ignored. So it should still work, but you may want to think about making those into capital I's so that Mathematica recognizes them as complex numbers. Certainly if you want to do any math on those numbers or plot them or something, it won't work well.
You can fix this pretty easily with list = list/.i->I
. This replaces any instance of "i" with I
. /.
is shorthand for ReplaceAll
, and the ->
indicates a rule for the replacement to follow.
EDIT to account for new cases:
It does become a bit trickier if you only want to return parts of rows based on certain conditions, so I've switched to Cases
. There may be a more concise way to write this code, but I haven't been able to come up with it so far. Keep in mind, for this code to work properly, "i" needs to have been replaced with "I".
The first part of the pattern {a_?NonNegative, b_?NonNegative, c_?NonNegative, {d_, e_}}
checks to make sure that a, b, c
are not negative.
/; AllTrue[d, NonNegative] \[Or] AllTrue[e, NonNegative]
tells it that a row is only valid if either the first 2 values of the matrix are non-negative OR the last 2 values are non-negative. If neither is non-negative, this row is skipped. /;
is short for Condition
(like a short If
statement, essentially).
:> {a, b, c, Which[AllTrue[d~Join~e, NonNegative], {d, e}, AllTrue[d, NonNegative], d, AllTrue[e, NonNegative], e]}
tells it what to return. :>
is shorthand for RuleDelayed
. If all the tests to the left of :>
have been passed, then a, b, c
will definitely be returned. The Which
statement says that if both d
and e
are non-negative, return {d, e}
. If only one of those is non-negative, then return whichever is non-negative.
Cases[
list,
{a_?NonNegative, b_?NonNegative, c_?NonNegative, {d_, e_}} /;
AllTrue[d, NonNegative] \[Or] AllTrue[e, NonNegative] :>
{a, b, c,
Which[
AllTrue[d~Join~e, NonNegative], {d, e},
AllTrue[d, NonNegative], d,
AllTrue[e, NonNegative], e
]
}
]
list[[-1]]
which gives{1, 2, 2, {{0.45, 2}, {0.399896, 7}}}
. If you mean the bottom right cell:list[[-1, -1]]
which gives{{0.45, 2}, {0.399896, 7}}
. If you really mean the very last list:list[[-1, -1, -1]]
which gives{0.399896, 7}
. I recommend playing around with selecting different parts of lists using the indices, and looking upPart
in the documentation system. The double square brackets are short-hand forPart
. $\endgroup$first
andlast
entries in a list also. So you can useLast@list
in place oflist[[-1]]
and these give same thing. $\endgroup$