18
\$\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\$
3
  • 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\$ Mar 10, 2015 at 20:49
  • \$\begingroup\$ Why isn't this in Stack Overflow? \$\endgroup\$ Mar 10, 2015 at 21:32
  • 14
    \$\begingroup\$ @BobTheAwesome I'm not asking for good ways to do this, just short ones. \$\endgroup\$
    – xnor
    Mar 10, 2015 at 21:32

3 Answers 3

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\$
4
  • 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, 2015 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, 2015 at 0:30
  • 1
    \$\begingroup\$ If you only need to do it once, can you do: vars()["xy"[b]]=z? \$\endgroup\$
    – aebabis
    Mar 11, 2015 at 19:37
  • \$\begingroup\$ @acbabis: yes, as xnor pointed out. \$\endgroup\$ Mar 11, 2015 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\$
1
  • 3
    \$\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, 2015 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\$
1
  • 8
    \$\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, 2015 at 7:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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