Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question
add comment

5 Answers 5

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}} *)
share|improve this answer
    
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
add comment

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.

share|improve this answer
    
It is really fast! –  yulinlinyu Dec 12 '12 at 11:29
1  
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
add comment

How about this?

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}
share|improve this answer
    
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
2  
maybe FreeQ[#, -1] & instead of Positive? –  kguler Dec 12 '12 at 10:18
add comment

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.

share|improve this answer
add comment

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]
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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