6
$\begingroup$

In a list lst I want to change all values > 255 to 255. Why is this code not working?

lst= {336, 315, 395, 337, 411, 309, 408, 338, 576, 377, 508, 386, 545, \
477, 453, 424, 425, 286, 363, 248, 298, 268, 221, 162, 184, 121, 164, \
124, 161, 109, 165, 150, 183, 111, 154, 132, 136, 88, 123, 388, 387, \
382, 375, 340, 325, 374, 324, 372, 295, 398, 361, 547, 418, 483, 381, \
517, 465, 454, 432, 414, 288, 342, 241, 281, 261, 218, 172, 165, 127, \
532, 392, 397, 345, 403, 375, 400, 342, ...}

inf = Flatten@Position[lst, _?(# > 255 &)];
ReplacePart[lst, inf -> 255]

It seems that it doesn't effect the list at all. Thanks a lot for opening my eyes...

$\endgroup$
3
  • 5
    $\begingroup$ By the way, your code works with the modification ReplacePart[lst, Thread[inf -> 255]] $\endgroup$ Commented Sep 12, 2012 at 7:00
  • $\begingroup$ @b.gatessucks Thanks again. Meanwhile I changed my code, using Clip ... $\endgroup$
    – Harald
    Commented Sep 12, 2012 at 7:08
  • $\begingroup$ Echoing George's comment, you asked "Why is this code not working?" R.M.'s method is surely more efficient, but it does not answer your question. IMHO you should try to Accept answers that actually do. $\endgroup$
    – Mr.Wizard
    Commented Sep 16, 2012 at 12:23

6 Answers 6

17
$\begingroup$

The function Clip does exactly what you want — it "clips" values between a minimum and a maximum. To clip only those values that are larger than a set threshold, use -∞ as the lower bound (and vice versa). So, all you need to do is:

Clip[lst, {-∞, 255}]
$\endgroup$
1
  • $\begingroup$ Thanks a lot!! Searching Wolfram's reference I didn't find that feature... So, thanks again for your hint $\endgroup$
    – Harald
    Commented Sep 12, 2012 at 6:43
12
$\begingroup$

Why not :

 Min[#, 255] & /@ lst
$\endgroup$
1
  • 1
    $\begingroup$ Thanks a lot, with Min[#, 255] & /@ lst it works fine $\endgroup$
    – Harald
    Commented Sep 12, 2012 at 6:54
10
$\begingroup$

Using syntax close to your original you could use:

lst /. _?(# > 255 &) -> 255

or

lst /. x_ /; x > 255 -> 255

And your original version works with this modification:

inf = Flatten@Position[lst, _?(# > 255 &)];
ReplacePart[lst, # -> 255 & /@ inf]
$\endgroup$
6
$\begingroup$

Your specific question was "Why is this code not working?" and not, how can I do this. Although it's probably clear now, the reason it didn't work is that you were misusing ReplacePart. Mathematica help's basic example shows this application:

ReplacePart[{a, b, c, d, e}, {2 -> xx, 5 -> yy}]
(* {a, xx, c, d, yy} *)

But your code didn't try to do exactly that. Tedious code to use ReplacePart would be:

p = Flatten[Position[lst, _?(# > 255 &)]];
vals = Table[255, {Length[p]}];
replacements = #[[1]] -> #[[2]] & /@ Transpose[{p, vals}];
lst=ReplacePart[lst, replacements];

b.gatessucks' answer does basically the same thing, but didn't exactly explain what was wrong with your code. I hope this is not a redundant answer.

$\endgroup$
1
  • 1
    $\begingroup$ Hello and welcome to the site! I've edited your answer to use the code highlighting (indent by 4 spaces). Re: your second question, it's not advised to answer serially like in a forum. Instead, you can edit this answer to include that info and delete that... $\endgroup$
    – rm -rf
    Commented Sep 16, 2012 at 1:10
4
$\begingroup$

The answer lies in a subtlety of the syntax of ReplacePart:

Mathematica graphics

Your code as written produces the syntax shown on the first line, so you are trying to replace a single part at the depth of Length @ inf, which of course doesn't exist.

What you need is the syntax shown on the third line where each part specification is in its own list. Ironically this form is output by Position directly, but you threw it away with Flatten. Therefore, your code may be fixed by simply removing that counterproductive operation:

lst = RandomInteger[500, 30];

inf = Position[lst, _?(# > 255 &)]
{{6}, {7}, {9}, {13}, {15}, {19}, {20}, {21}, {22}, {23}, {27}, {29}, {30}}
ReplacePart[lst, inf -> 255]
{178, 49, 94, 66, 123, 255, 255, 169, 255, 143, 109, 153, 255, 100, 255, 142,
 149, 64, 255, 255, 255, 255, 255, 169, 30, 143, 255, 97, 255, 255}
$\endgroup$
4
$\begingroup$

This also works:

p = Flatten[Position[lst, _?(# > 255 &)]];
(lst[[#]] = 255) & /@ p;

or as a one liner:

(lst[[#]] = 255) & /@ Flatten[Position[lst, _?(# > 255 &)]]
$\endgroup$

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