5
$\begingroup$

I would like to apply a random color to several list elements. For example:

Style[{x, y}, RandomColor[]]

enter image description here

makes the list itself colored. But I want the elements to be colored separately, not the list itself. If I do

(Style[#, RandomColor[]] &) /@ {x, y}

enter image description here

only the elements get colored, but they get a different color each. Of course I can fix this by writing

rColor[x_]:=Block[{rd},
  rd=RandomColor[];
  (Style[#, rd] &) /@ x
]

So that

rColor[{x, y}]

enter image description here

which is the desired output. But it just does not feel right to write a whole block for such a simple function. Is there a one-line solution that produces the desired output?

$\endgroup$
  • 3
    $\begingroup$ randomStyle[] := With[{c = RandomColor[]}, Style[#, c] &]; randomStyle[] /@ Range[10] You can leave off the [] from randomStyle, but I prefer it this way because it makes it clear that randmoStyle evaluates once and returns something (another function). $\endgroup$ – Szabolcs Dec 2 '16 at 19:52
  • 1
    $\begingroup$ I didn't post it because I thought it wasn't different enough from Bill's. It just encapsulates the colour into the generated function. @bills With replaces c by an actual colour within the Function. Block would just give a temporary value to c, but c still exist as a variable that needs to be evaluated to get the colour. $\endgroup$ – Szabolcs Dec 2 '16 at 20:03
  • 1
    $\begingroup$ @bills I might be wrong, but I believe Block transports the entire input to a local scope, applies the operations within the Block and returns the entire list as an output. The With modifies the function itself before it is applied. $\endgroup$ – Kagaratsch Dec 2 '16 at 20:04
  • 1
    $\begingroup$ BlockRandom[Style[#, RandomColor[]] ]& /@ {x, y, z, w}? $\endgroup$ – kglr Dec 2 '16 at 20:12
  • 2
    $\begingroup$ @Kagaratsch, you can get different colors in every invocation using RandomColor[]; BlockRandom[Style[#, RandomColor[]] ]& /@ {x, y,z,w}, but your rColor is much cleaner than this. $\endgroup$ – kglr Dec 2 '16 at 20:21
9
$\begingroup$

Not so fancy:

Thread[Style[{x, y}, RandomColor[]]]
$\endgroup$
  • $\begingroup$ Using this as rColor[x_] := Thread[Style[x, RandomColor[]]] is perfect! Thank you! $\endgroup$ – Kagaratsch Dec 2 '16 at 20:33
5
$\begingroup$

I love Stitch's work-around, but following the logic that sometimes Thread cannot replace Map another method is to simply pre-evaluate the body of the Function wish you map. This is essentially what Szabolcs's proposal does but a bit more direct.

Evaluate @ Style[#, RandomColor[]] & /@ {1, 2, 3}

enter image description here

An example usage contrasting with Thread is when you want a different levelspec:

Map[
  Evaluate @ Style[#, RandomColor[]] &,
  {{1, 2}, {3, 4}, {5, 6}},
  {2}
]

enter image description here

$\endgroup$
1
$\begingroup$

This should work:

rc = RandomColor[]; Style[#, rc] & /@ {x, y}
$\endgroup$
  • 1
    $\begingroup$ I should have mentioned that I plan to use the function in a larger expression, so that saving the random color to a separate variable before applying the Style is exactly what I would like to avoid. (In this sense, your code is equivalent to my hacky solution using Block.) $\endgroup$ – Kagaratsch Dec 2 '16 at 19:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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