19
\$\begingroup\$

This is a question for golfing in .

In multiple golfs I've done in Python, a fixed value is assigned to one of two variables chosen by a Boolean. The chosen variable is overwritten by the given value, and the other is unchanged.

17 chars:

if b:y=z
else:x=z

Assigning a conditional value is easy, but assigning to a conditional variable seems clunky. I'm wondering if there's a shorter way I'm missing.

This would be easy if x,y were instead a list L, but assume the context requires referring to the variables enough that writing L[0] and L[1] is prohibitive. Converting takes too long:

20 chars:

L=[x,y];L[b]=z;x,y=L

The fastest way I know is with a Python 2 exec, which is bizarre:

16 chars, Python 2:

exec"xy"[b]+"=z"

Tuple-choosing seems to be longer:

18, 19, 18, 18 chars:

x,y=b*(x,z)or(z,y)
x,y=[z,x,y,z][b::2]
y,x=[y,z,x][b:b+2]
y,x,*_=[y,z,x][b:]   # Python 3 

Is there some shorter method or character-saving optimization? You can assume b is 0 or 1, not just Falsey or Truthy, and also make assumptions about the data types and values if it helps.

\$\endgroup\$
  • 1
    \$\begingroup\$ I don't know of anything better. If you need to do this a lot, you can do x,y=C(x,y,z,b) (14 chars) and push any of these implementations into the body of C. \$\endgroup\$ – Keith Randall Mar 10 '15 at 20:49
  • \$\begingroup\$ Why isn't this in Stack Overflow? \$\endgroup\$ – BobTheAwesome Mar 10 '15 at 21:32
  • 14
    \$\begingroup\$ @BobTheAwesome I'm not asking for good ways to do this, just short ones. \$\endgroup\$ – xnor Mar 10 '15 at 21:32
26
\$\begingroup\$

12 chars/assignment + 9 chars of overhead

V=vars()     # do once at the start of the program
V["xy"[b]]=z

Note that this only works at global scope, it does not work inside a function.

\$\endgroup\$
  • 1
    \$\begingroup\$ Wow, I did not know about this. And it's cool that V updates automatically, with no need to call the function again. So this breaks even with exec in two uses. Also, just doing vars()["xy"[b]]=z is 17 chars, which is the best we have so far for Python 3, without the control flow of if/else which can cause problems. \$\endgroup\$ – xnor Mar 10 '15 at 21:26
  • 3
    \$\begingroup\$ It's actually 9 chars of overhead because a newline or semicolon must follow the assignment. \$\endgroup\$ – xnor Mar 11 '15 at 0:30
  • 1
    \$\begingroup\$ If you only need to do it once, can you do: vars()["xy"[b]]=z? \$\endgroup\$ – aebabis Mar 11 '15 at 19:37
  • \$\begingroup\$ @acbabis: yes, as xnor pointed out. \$\endgroup\$ – Keith Randall Mar 11 '15 at 22:06
19
\$\begingroup\$

14 chars, Python 2

exec"xy=z"[b:]

The two variables are y and xy. If b=0, this sets xy=z. If b=1, this sets y=z. This will be worth it if xy is used no more than once elsewhere in the code.

\$\endgroup\$
  • 2
    \$\begingroup\$ Very clever! I suspect you usually need to use xy at least twice though, for its initial assignment, and to read it out afterwards. \$\endgroup\$ – xnor Mar 10 '15 at 21:27
15
\$\begingroup\$

15 chars, Python 2

exec`b`[0]+"=z"

Requires that the variables be called F and T rather than x and y, and that b is False or b is True, rather than being the equal numbers 0 or 1.

This saves a char from "xy"[b] by instead taking the first letter of the string representation of b, which is T or F.

\$\endgroup\$
  • 7
    \$\begingroup\$ Note that the variables can also be called a and r, l and u or s and e, with appropriate indices. \$\endgroup\$ – isaacg Mar 11 '15 at 7:18

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.