Mathematica: An idiomatic way to replace values ​​in a list that matches a condition?

I want to trim the absolute values ​​below epsilon to 0, e.g.

Truncate[{-3, -2, -1, 0, 1, 2, 3}, 1.5] -> {-3, -2, 0, 0, 0, 2, 3} 

I think I could write a function using Scan [] and If [], but is there a more idiomatic “one-line” way to do this in Mathematica?

+4
source share
3 answers

The built-in Chop function is almost what you are looking for (it works in lists, as in your example). One potential surprise is that it does not interrupt (truncate) integers, but only floating point numbers. Therefore, for your example to work as you might expect, first convert your list to a floating point using function N :

 Chop[ N@ {-3, -2, -1, 0, 1, 2, 3}, 1.5] -> {-3., -2., 0, 0, 0, 2., 3.} 

As Ramashalanka shows, in order to do this more generally, I recommend:

 If[Abs[#]<1.5&, 0, #]& /@ {-3, -2, -1, 0, 1, 2, 3} 

That is, the lambda function is displayed above the list.

+5
source

Lots of options that all work:

 Map[If[Abs[#] < 1.5, 0, #] &, {-3, -2, -1, 0, 1, 2, 3}] 

or equivalent:

 If[Abs[#] < 1.5, 0, #] & /@ {-3, -2, -1, 0, 1, 2, 3} 

or if you want:

 ReplaceAll[{-3, -2, -1, 0, 1, 2, 3}, (x_ /; Abs[x] < 1.5) -> 0] 

which is equivalent to:

 {-3, -2, -1, 0, 1, 2, 3} /. (x_ /; Abs[x] < 1.5) -> 0 

or

 ReplaceAll[{-3, -2, -1, 0, 1, 2, 3}, (x_?(Abs[#] < 1.5 &)) -> 0] 

which is equivalent to:

 {-3, -2, -1, 0, 1, 2, 3} /. (x_?(Abs[#] < 1.5 &)) -> 0 
+6
source

Here is the method ( f3 ), which is almost an order of magnitude faster.

It is adapted from the code of Fred Simons.


 f1 = If[Abs[#] < 1.5, 0, #] & /@ # &; f2 = # /. (x_ /; Abs[x] < 1.5) -> 0 &; f3 = # (1 - Unitize@Clip [#, {-1.5, 1.5}, {0, 0}]) &; lst = RandomInteger[{-100, 100}, 5000]; SameQ @@ (#@lst & /@ {f1, f2, f3}) First@Timing @Do[#@lst, {500}] & /@ {f1, f2, f3} (* Out= True *) (* Out= {0.406, 2.282, 0.047} *) 
+1
source

Source: https://habr.com/ru/post/1300942/


All Articles