How to change specific values in a List [duplicate]

This question already has an answer here:

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...

-

marked as duplicate by Mr.Wizard♦Feb 2 '14 at 7:35

By the way, your code works with the modification ReplacePart[lst, Thread[inf -> 255]] – b.gatessucks Sep 12 '12 at 7:00
@b.gatessucks Thanks again. Meanwhile I changed my code, using Clip ... – Harald Sep 12 '12 at 7:08
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. – Mr.Wizard Sep 16 '12 at 12:23

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}]

-
Thanks a lot!! Searching Wolfram's reference I didn't find that feature... So, thanks again for your hint – Harald Sep 12 '12 at 6:43

Why not :

 Min[#, 255] & /@ lst

-
Thanks a lot, with Min[#, 255] & /@ lst it works fine – Harald Sep 12 '12 at 6:54

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]

-

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.

-
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... – R. M. Sep 16 '12 at 1:10

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

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}

-

This also works:

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


or as a one liner:

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

-