remove -1 values from a list

I would like to turn a list which looks like this one:

{{-1, -1, -1}, {-1, 2, 3}, {-1, -1, 2}, {2, 3, 4}}


into one which looks like that one:

{{}, {2, 3}, {2}, {2, 3, 4}}


Is there an efficient way to do this?

-
list /. -1 -> Nothing – garej Apr 6 at 19:55

This :

data = {{-1, -1, -1}, {-1, 2, 3}, {-1, -1, 2}, {2, 3, 4}};
DeleteCases[data, -1, Infinity]


Addressing @Sjoerd's comment, if the list is 2 dimensional one can adjust the level to 2.

data2 = {{-1, -1, -1}, {-1, 2, 3, Exp[-1]}, {-1, -1, 2}, {2, 3, 4}};
DeleteCases[data2, -1, 2]
(* {{}, {2, 3, 1/E}, {2}, {2, 3, 4}} *)

-
Goes wrong if the data contains elements such as Exp[-1]. Only @Mr.Wizard's solution works there. – Sjoerd C. de Vries Dec 16 '12 at 13:33
@SjoerdC.deVries Good point, thanks, would my edit fix this ? – b.gatessucks Dec 16 '12 at 13:42
It does for two dimensional lists, and it looks like the OP is assuming that. – Sjoerd C. de Vries Dec 16 '12 at 14:15

Replacing -1 with an empty Sequence should do it:

lst = {{-1, -1, -1}, {-1, 2, 3}, {-1, -1, 2}, {2, 3, 4}};

(* In *)
lst /. {-1 -> Sequence[]}
(* Out *)
{{}, {2, 3}, {2}, {2, 3, 4}}


If there are expressions containing -1 that shouldn't be replaced, and your list is always of depth 2, you can use Replace instead of ReplaceAll:

lst = {{Exp[-1], -1, -1}, {-1, 2, 3}, {-1, -1, 2}, {2, 3, 4}};

Replace[lst, {-1 -> Sequence[]}, {2}]


Comparing this solution with the DeleteCases solution from b.gatessucks, it seems the DeleteCases solution is faster:

AbsoluteTiming[Do[lst /. {-1 -> Sequence[]}, {100000}]] // First
(* Out *)
0.763795

AbsoluteTiming[Do[DeleteCases[lst, -1, Infinity], {100000}]] // First
(* Out *)
0.448700


Some other alternatives based on the answer by yulinlinyu (and comments):

AbsoluteTiming[Do[Select[#, FreeQ[#, -1] &] & /@ lst, {100000}]] // First
(* Out *)
2.153360

AbsoluteTiming[Do[Cases[#, Except[-1]] & /@ lst, {100000}]] // First
(* Out *)
1.045021


If the actual lst is larger, the tests may come out differently, but I would suspect not.

-
It is really fast! – yulinlinyu Dec 12 '12 at 11:29
Goes wrong if the data contains elements such as Exp[-1]. Only Mr.Wizard's solution works there. – Sjoerd C. de Vries Dec 16 '12 at 13:33
@SjoerdC.deVries: You are right. I added an alternative way using Replace covering this. – Malte Lenz Dec 17 '12 at 10:04

If your (ragged) array is entirely numeric, and your desired operation is to remove all negative values, you could use this:

Pick[#, UnitStep@#, 1] & @ {{-1, -1, -1}, {-1, 2, 3}, {-1, -1, 2}, {2, 3, 4}}

{{}, {2, 3}, {2}, {2, 3, 4}}


This should prove competitively fast as well.

-

Select[#, Positive] & /@ {{-1, -1, -1}, {-1, 2, 3}, {-1, -1, 2}, {2,
3, 4}}


Edit 1:

 According to Lenz's and Kguler's advice, the code can be

Select[#, FreeQ[#,-1]&] & /@ {{-1, -1, -1}, {-1, 2, 3}, {-1, -1, 2}, {2,
3, 4}}


Or

    Select[#, #!=-1&] & /@ {{-1, -1, -1}, {-1, 2, 3}, {-1, -1,
2}, {2, 3, 4}}


Edit 2:

 According to the op's comment below, the codes can be something like this:

Select[#, FreeQ[#,-1]&] & /@ {{-1, -1, -1}, {-1, 2, 3}, {-1, -1, 2}, {2,
3, 4}}/.{}->{0,0}

-
This would also remove elements of other negative numbers, which the title of the question indicates is not the wanted scenario. – Malte Lenz Dec 12 '12 at 10:10
thank you for the nice answers. If the result of a sublist is {} it should be turned into {0,0}. How can I do this? – RMMA Dec 12 '12 at 10:14
You could add this as a requirement to the original question. Replacing empty lists with ReplaceAll should be a good way though. – Malte Lenz Dec 12 '12 at 10:17
maybe FreeQ[#, -1] & instead of Positive? – kglr Dec 12 '12 at 10:18

Translation of python.

Table[If[j != -1, j, ## &[]], {i, list}, {j, i}]

 [[j for j in i if j != -1] for i in list]


A recursive version:

foo[L_] := Table[If[ListQ[i], foo[i], If[i != -1, i, ## &[]]], {i, L}];
foo[list]

-