255
\$\begingroup\$

What general tips do you have for golfing in Python? I'm looking for ideas which can be applied to code-golf problems and which are also at least somewhat specific to Python (e.g. "remove comments" is not an answer).

Please post one tip per answer.

\$\endgroup\$
  • 27
    \$\begingroup\$ Oh, I can see a whole set of questions like this one coming for each language... \$\endgroup\$ – R. Martinho Fernandes Jan 28 '11 at 4:26
  • 4
    \$\begingroup\$ @Marthinho I agree. Just started a C++ equivalent. I don't think its a bad thing though, as long as we don't see the same answers re-posted across many of these question types. \$\endgroup\$ – marcog Jan 28 '11 at 12:28
  • 50
    \$\begingroup\$ Love the question but I have to keep telling myself "this is ONLY for fun NOT for production code" \$\endgroup\$ – Greg Guida Dec 21 '11 at 0:08
  • 2
    \$\begingroup\$ Shouldn't this question be a community wiki post? \$\endgroup\$ – user8397947 May 29 '16 at 15:35
  • 3
    \$\begingroup\$ @dorukayhan Nope; it's a valid code-golf tips question, asking for tips on shortening python code for CG'ing purposes. Such questions are perfectly valid for the site, and none of these tags explicitly says that the question should be CW'd, unlike SO, which required CG challenges to be CW'd. Also, writing a good answer, and finding such tips always deserves something, that is taken away if the question is community wiki (rep). \$\endgroup\$ – Erik the Outgolfer Sep 9 '16 at 14:48

145 Answers 145

9
\$\begingroup\$

If you want to know the type of a variable x:

x*0is 0  # -> integer
x*0==0   # -> float (if the previous check fails)
x*0==""  # -> string
x*0==[]  # -> array
\$\endgroup\$
8
\$\begingroup\$

use os.urandom() as a random source instead of random.randint()

\$\endgroup\$
  • 1
    \$\begingroup\$ Doesn't this require use of ord() to get a number instead of character? len("ord(os.urandom(1))") -> 18 and len("random.randint()") -> 16 \$\endgroup\$ – jscs May 1 '11 at 3:10
  • 3
    \$\begingroup\$ @Josh, don't forget you need to import random vs import os. randint() needs 3 parameters anyway. If you need a list of random numbers, you can use map(ord,os.urandom(N)) Also, sometimes, you actually need a random char instead of a number \$\endgroup\$ – gnibbler May 1 '11 at 7:17
  • 3
    \$\begingroup\$ Late to the party, but if you only need a few random numbers, try using id(id), substituting the inner id with any 3-letter builtin if you need more than one. 'abc'[id(id)%3] is 11 characters shorter than 'abc'[random.randrange(3)], not even counting the import statement. \$\endgroup\$ – Fraxtil Apr 20 '13 at 2:04
  • \$\begingroup\$ @Fraxtil id can be applied on mostly everything, such as 1 or []. \$\endgroup\$ – user202729 Jul 5 '18 at 9:41
8
\$\begingroup\$

Leak variables to save on assignment

Combining with this tip, suppose you have a situation like

for _ in[0]*x:doSomething()
a="blah"

You can instead do:

for a in["blah"]*x:doSomething()

to skip out on a variable assignment. However, be aware that

exec"doSomething();"*x;a="blah"

in Python 2 is just shorter, so this only really saves in cases like assigning a char (via "c"*x) or in Python 3.

However, where things get fun is with Python 2 list comprehensions, where this idea still works due to a quirk with list comprehension scope:

[doSomething()for a in["blah"]*x]

(Credits to @xnor for expanding the former, and @Lembik for teaching me about the latter)

\$\endgroup\$
  • \$\begingroup\$ Does the last one not work in Python 3? \$\endgroup\$ – xnor Jun 26 '15 at 17:29
  • \$\begingroup\$ @xnor in Python 3 exec requires parentheses, so it would be one character longer than the for... format. \$\endgroup\$ – Coty Johnathan Saxman Jul 14 '17 at 7:10
8
\$\begingroup\$

Use powers of the imaginary unit to calculate sines and cosines.

For example, given an angle d in degrees, you can calculate the sine and cosine as follows:

p=1j**(d/90.)
s=p.real
c=p.imag

This can also be used for related functions such as the side length of a unit n-gon:

l=abs(1-1j**(4./n))
\$\endgroup\$
  • 2
    \$\begingroup\$ Does... Does this also become a math golfing tip? o0 \$\endgroup\$ – totallyhuman Oct 31 '17 at 1:14
8
\$\begingroup\$

Split into chunks

You can split a list into chunks of a given size using zip and iter, as explained in this SO question.

>>> l=range(12)
>>> zip(*[iter(l)]*4)
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)]

Of course, substituting in l as zip(*[iter(range(12))]*4) gives the same result.

The 4 is the number of elements per chunk. If the length isn't a multiple of this, any elements in the remainder are not included. For example, l=range(13) would give the same result.

The result is a list of tuples. If your input is a string and you want to produce a list of strings, you can do

>>> l="Code_golf"
>>> map(''.join,zip(*[iter(l)]*3)) 
['Cod', 'e_g', 'olf'] # Python 3 would give a map object

When the list l is defined by a list comprehension, instead of converting to an iterable as iter(l), you can instead write it as a generator comprehension with (...) instead of [...].

>>> l=(n for n in range(18)if n%3!=1)
>>> zip(*[l]*4)
[(0, 2, 3, 5), (6, 8, 9, 11), (12, 14, 15, 17)]

This consumes the generator, so l will appear empty afterwards. Note as before that we can inline l as zip(*[(n for n in range(18)if n%3!=1)]*4).

\$\endgroup\$
7
\$\begingroup\$

Abuse the fact that in case of an expression yielding True boolean operators return the first value that decides about the outcome of the expression instead of a boolean:

>>> False or 5
5

is pretty straightforward. For a more complex example:

>>> i = i or j and "a" or ""

i's value remains unchanged if it already had a value set, becomes "a" if j has a value or in any other case becomes an empty string (which can usually be omitted, as i most likely already was an empty string).

\$\endgroup\$
  • 3
    \$\begingroup\$ Shorter: i=i or j and"a"or"" \$\endgroup\$ – nyuszika7h Aug 18 '14 at 16:46
7
\$\begingroup\$

Lets play with some list tricks

a=[5,5,5,5,5,5,5]

can be written as:

a=[5]*7

It can be expanded in this way. Lets, say we need to do something like

for i in range(0,100,3):a[i]=5

Now using the slicing trick we can simply do:

a[0:100:3]=[5]*(1+99//3)
\$\endgroup\$
  • 4
    \$\begingroup\$ last example, of course, must be written a[:100:3]=[5]*34 \$\endgroup\$ – AMK Dec 16 '13 at 18:57
  • 3
    \$\begingroup\$ @AMK yap i know ;) But i kept that way cause people may get hard time guessing how i got 34. it just from the formula (1+(100-1)//3) where 100 is number of elements and 3 is the step. Thanks for pointing it :D \$\endgroup\$ – Wasi Dec 16 '13 at 19:03
7
\$\begingroup\$

Use eval to iterate

Say you want to apply f composed k times to the number 1, then print the result.

This can be done via an exec loop,

n=1
exec("n=f(n);"*k)
print(n)

which runs code like n=1;n=f(n);n=f(n);n=f(n);n=f(n);n=f(n);print(n).

But, it's one character shorter to use eval

print(eval("f("*k+'1'+")"*k))

which evaluates code like f(f(f(f(f(1))))) and prints the result.

This does not save chars in Python 2 though, where exec doesn't need parens but eval still does. It does still help though when f(n) is an expression in which n appears only once as the first or last character, letting you use only one string multiplication.

\$\endgroup\$
7
\$\begingroup\$

Use map for side effects

Usually you use map to transform a collection

>> map(ord,"abc")
[97, 98, 99]

But you can also use it to repeatedly act on object by a built-in method that modifies it.

>> L=[1,2,3,4,5]
>> map(L.remove,[4,2])
[None, None]
>> L
[1, 3, 5]

Be aware that the calls are done in order, so earlier ones might mess up later ones.

>> L=[1,2,3,4,5]
>> map(L.pop,[0,1])
[1, 3]
>> L
[2, 4, 5]

Here, we intended to extract the first two elements of L, but after extracting the first, the next second element is the original third one. We could sort the indices in descending order to avoid this.

An advantage of the evaluation-as-action is that it can be done inside of a lambda. Be careful in Python 3 though, where map objects are not evaluated immediately. You might need an expression like 0in map(...) to force evaluation.

\$\endgroup\$
7
\$\begingroup\$

Logical short-circuiting in recursive functions

A detailed guide

I had worked with short-circuiting and/or's for a while without really grasping how they work, just using b and x or y just as a template. I hope this detailed explanation will help you understand them and use them more flexibly.


Recursive named lambda functions are often shorter than programs that loop. For evaluation to terminate, there must be control flow to prevent a recursive call for the base case. Python has a ternary condition operator that fits the bill.

f=lambda x:base_value if is_base_case else recursive_value

Note that list selection won't work because Python evaluates both options. Also, regular if _: isn't an option because we're in a lambda.


Python has another option to short-circuit, the logical operator keywords and and or. The idea is that

True or b == True
False and b == False

so Python can skip evaluate b in these cases because the result is known. Think of the evaluation of a or b as "Evaluate a. If it's True, output a. Otherwise, evaluate and output b." So, it's equivalent to write

a or b
a if a else b

It's the same for a or b except we stop if a is False.

a and b
a if (not a) else b

You might wonder why we didn't just write False if (not a) else b. The reason is that this works for non-Boolean a. Such values are first converted to a Boolean. The number 0, None, and the empty list/tuple/set become False, and are so called "Falsey". The rest are "Truthy".

So, a or b and a and b always manages to produce either a or b, while forming a correct Boolean equation.

(0 or 0) == 0
(0 or 3) == 3
(2 or 0) == 2
(2 or 3) == 2
(0 and 0) == 0
(0 and 3) == 0
(2 and 0) == 0
(2 and 3) == 3
('' or 3) == 3
([] and [1]) == []
([0] or [1]) == [0]

Now that we understand Boolean short-circuiting, let's use it in recursive functions.

f=lambda x:base_value if is_base_case else recursive_value

The simplest and most common situation is when the base is something like f("") = "", sending a Falsey value to itself. Here, it suffices to do x and with the argument.

For example, this function doubles each character in a string, f("abc") == "aabbcc".

f=lambda s:s and s[0]*2+f(s[1:])

Or, this recursively sums the cubes of numbers 1 through n, so f(3)==36.

f=lambda n:n and n**3+f(n-1)

Another common situation is for your function to take non-negative numbers to lists, with a base case of 0 giving the empty list. We need to transform the number to a list while preserving Truthiness. One way is n*[5], where the list can be anything nonempty. This seems silly, but it works.

So, the following returns the list [1..n].

f=lambda n:n*[5]and f(n+1)+[n]  

Note that negative n will also give the empty list, which works here, but not always. For strings, it's similar with any non-empty string. If you've previously defined such a value, you can save chars by using it.

More generally, when your base value is an empty list, you can use the arithmetic values True == 1 and False == 0 to do:

[5]*(is_not_base_case)and ...

TODO: Truthy base value


TODO: and/or

\$\endgroup\$
  • \$\begingroup\$ An easy way to explain how and and or work might be: x or y=if x:return x;return y x and y:if x:return y;return x \$\endgroup\$ – fejfo Jan 11 '18 at 19:47
7
\$\begingroup\$

One trick I have encountered concerns returning or printing Yes/No answers:

 print 'YNeos'[x::2]

x is the condition and can take value 0 or 1.

I found this rather brilliant.

\$\endgroup\$
  • 3
    \$\begingroup\$ Welcome to PPCG! It seems that this is mostly a special case of this tip though. \$\endgroup\$ – Martin Ender Apr 14 '16 at 16:26
7
\$\begingroup\$

A condition like

s = ''
if c:
    s = 'a'

can be written as

s = c*'a'

and there is possibly a need for parenthesis for condition.

This can also be combined with other conditions as (multiple ifs)

s = c1*'a' + c2*'b'

or (multiple elifs)

s = c1*'a' or c2*'b'

For example FizzBuzz problem's solution will be

for i in range(n):
    print((i%3<1)*"Fizz"+(i%5<1)*"Buzz" or i)
\$\endgroup\$
6
\$\begingroup\$

List comprehension.

shortList = []
for x in range(10):
    shortList += [x * 2]

can be shortened into

shortList = [x*2 for x in range(10)]

Or even shorter:

shortList = range(0,20,2)
\$\endgroup\$
  • \$\begingroup\$ Can even be shortened (by a character) to [x**2for x in range(10)] \$\endgroup\$ – TerryA May 13 '13 at 11:31
  • \$\begingroup\$ @Haidro I think you mean [x*2for x in range(10)] \$\endgroup\$ – Timtech Dec 8 '13 at 17:58
  • \$\begingroup\$ @Timtech You are right :) \$\endgroup\$ – TerryA Dec 8 '13 at 19:13
6
\$\begingroup\$

If you are doing something small in a for loop whose only purpose is to invoke a side effect (pop, print in Python 3, append), it might be possible to translate it to a list-comprehension. For example, from Keith Randall's answer here, in the middle of a function, hence the indent:

  if d>list('XXXXXXXXX'):
   for z in D:d.pop()
   c=['X']

Can be converted to:

  if d>list('XXXXXXXXX'):
   [d.pop()for z in D]
   c=['X']

Which then allows this golf:

  if d>list('XXXXXXXXX'):[d.pop()for z in D];c=['X']

An if within a for works just as well:

for i in range(10):
 if is_prime(i):d.pop()

can be written as

[d.pop()for i in range(10)if is_prime(i)]
\$\endgroup\$
6
\$\begingroup\$

Object method as answer

Your submission can be a method of an object

range(123,790,111).count

This defines an anonymous function much shorter than

lambda n:range(123,790,111).count(n)

The object method is a valid function that meets our definition. For example, it could be bound and called

f=range(123,790,111).count
print f(99)

Because it avoids a costly lambda, this saves characters even rewriting from

lambda n:n in range(123,790,111)

Consider using an object method when your solution is a simple two-input function of your input and some concrete object. You can use dir() to get a list of methods of an object. Note in particular methods like .__add__ that are called for an operator like +. Most infix operators correspond to a method.

Other examples:

"prefix{}suffix".format
lambda s:"prefix"+s+"suffix"

2 .__rpow__    #Space for lexer
lambda n:n*n

[0,0].__le__
lambda l:[0,0]<=l

["North","East","South","West"].pop
lambda n:["North","East","South","West"][n]

You can even something save bytes with two input by currying. For example, compare

lambda l:expression_in_l.count
lambda n,l:n in expression_in_l

where expression_in_l produces a list with no duplicates and has favorable spacing and precedence.

\$\endgroup\$
  • 2
    \$\begingroup\$ ["North","East","South","West"].pop a function submission must work multiple times, no? using .__getitem__ would do the trick, but the length would be the same \$\endgroup\$ – Felipe Nardi Batista Jul 12 '17 at 13:51
6
\$\begingroup\$

When mapping a function on a list in Python 3, instead of doing [f(x)for x in l] or list(map(f,l)), do [*map(f,l)].

It works for all other functions returning generators too (like filter).

The best solution is still switching to Python 2 though

\$\endgroup\$
6
\$\begingroup\$

Format() works on dates:

"We are in year: %s" % (date.strftime('%y'))

Becomes:

"We are in year: {:%y}".format(date)

Or even better with f-strings:

f"We are in year: {date:%y}"
\$\endgroup\$
6
\$\begingroup\$

Check if a number is a power of 2

Check whether a positive integer n is a perfect power of 2, that is one of 1, 2, 4, 8, 16, ..., with any of these expression:

n&~-n<1
n&-n==n
2**n%n<1

This is shorter than converting to binary or using a loop. The last one also works for checking, say, powers of 3.

\$\endgroup\$
5
\$\begingroup\$

Sometimes you need convert boolean expression into integer (0/1) Simple use this Boolean (in examples below c > 0) in ariphmetic

a=b+(c>0)
a+=c>0
a=sum(c>0 for c in b) # space in "0 for" may be omitted

And sometimes you need simple convert boolean to int (for example for printing or convert to binary string). In programm you may use some variants

1 if c>0 else 0
c>0and 1or 0
(0,1)[c>0]
int(c>0)

but shortest way is

+(c>0)
\$\endgroup\$
  • 7
    \$\begingroup\$ I find +c being shorter. E.g. let c be a boolean, then 4+c is 5 if c is True else 4. \$\endgroup\$ – MyGGaN Feb 25 '14 at 23:41
5
\$\begingroup\$

Build a string instead of joining

To concatenate strings or characters, it can be shorter to repeatedly append to the empty string than to join.

23 chars

s=""
for x in l:s+=f(x)

25 chars

s="".join(f(x)for x in l)

Assume here that f(x) stands for some expression in x, so you can't just map.

But, the join may be shorter if the result doesn't need saving to a variable or if the for takes newlines or indentation.

\$\endgroup\$
5
\$\begingroup\$

String keys to dicts

For a dictionary with string keys which also happen to be valid Python variable names, you can get a saving if there's at least three items by using dict's keyword arguments:

{'a':1,'e':4,'i':9}
dict(a=1,e=4,i=9)

The more string keys you have, the more quote characters you'll save, so this is particularly beneficial for large dictionaries (e.g. for a kolmogorov challenge).

\$\endgroup\$
5
\$\begingroup\$

When squaring single letter variables, it is shorter to times it by itself

>>> x=30
>>> x*x
900

Is one byte shorter than

>>> x=30
>>> x**2
900
\$\endgroup\$
5
\$\begingroup\$

If transforming from list to a tuple or set to a set, list or tuple is needed, as of Python 3.5 you can use the splat operator:

tuple(iterable) -> (*iterable,)  (-3 bytes)
set(iterable)   -> {*iterable}   (-2 bytes)
list(iterable)  -> [*iterable]   (-3 bytes)

If you're doing this as well as appending/prepending, you can do the following for an extra bonus:

iterable+[1]       -> *iterable,1          (-2 bytes, 3 for tuples)
iterable+iter2     -> *iterable,*iterable2 (+1 byte, 0 for tuples, though can combine types)
[1]+iterable+[1]   -> 1,*iterable,1        (-3 bytes, -4 for tuples)
iterable+[1]+iter2 -> *iterable,1,*iter2   (0 bytes, -1 for tuples)

Basically, ,* instead of , gives a +1 byte penalty and , instead of ,[] gives -2 bytes.

This shows [1,*iterable,1] is a golfier way of doing [1]+iterable+[1] by one byte, even when we're not doing any type conversion.

And just for fun, {*{}} is the same length as set() for challenges without letters.

\$\endgroup\$
  • 1
    \$\begingroup\$ The last one can also be useful if there is a letter preceding set() (e.g. ...and set() can become ...and{*{}}). Oh, and it can be replaced with {*()} or {*[]} if an empty dict feels unsettling. ;-) \$\endgroup\$ – Erik the Outgolfer Jun 29 '18 at 22:37
4
\$\begingroup\$

Be aware of all, any and map:

if isdigit(a) and isdigit(b) and isdigit(c)
if all(map(isdigit,[a,b,c]))
\$\endgroup\$
  • 4
    \$\begingroup\$ filter(function, iterable) returns a list of all the elements of iterable` for which function is a True-y value and a non-empty list is True-y, so this can be shortened further to if filter(isdigit,[a,b,c]) \$\endgroup\$ – undergroundmonorail Apr 16 '14 at 8:33
  • 1
    \$\begingroup\$ Over a year later, I'm reading this thread again and I'm embarrassed about my previous comment. if filter(isdigit,[a,b,c]) is not equivalent to the code in the answer; but it would be if @moose used isdigit(a) or... and if any(.... \$\endgroup\$ – undergroundmonorail Apr 21 '15 at 13:36
4
\$\begingroup\$

If you need to import a lot of modules you can reassign __import__ to something shorter, this also has the advantage of being able to name imports anything you want.

i=__import__;s=i('string');x=i('itertools');
\$\endgroup\$
  • 2
    \$\begingroup\$ I've rarely found this to be actually useful. Generally import string,itertools, import string,itertools as M, from itertools import* and other variants tend to be shorter... \$\endgroup\$ – Sp3000 Jul 25 '15 at 9:05
  • \$\begingroup\$ s,i=map(__import__,['string','itertools']) is shorter than your example, but still longer than import string as s,itertools as i \$\endgroup\$ – Felipe Nardi Batista Jul 12 '17 at 14:44
4
\$\begingroup\$

Cut out newlines wherever you can.

At the top-level, it doesn't matter.

a=1
b=9

Takes the same amount of characters as:

a=1;b=9

In the first case you have a newline instead of a ;. But in function bodies, you save however deep the nesting level is:

def f():
 a=1;b=9

Actually in this case, you can have them all on one line:

def f():a=1;b=9

If you have an if or a for, you can likewise have everything on one line:

if h:a=1;b=9
for g in(1,2):a=1;b=9

But if you have a nesting of control structures (e.g. if in a for, or if in a def), then you need the newline:

if h:for g in(1,2):a=1;b=9 #ERROR

if h:
 for g in(1,2):a=1;b=9 # SAUL GOODMAN
\$\endgroup\$
  • \$\begingroup\$ You can use a,b=1,9 \$\endgroup\$ – Oliver Ni Jan 4 '15 at 1:24
  • \$\begingroup\$ It's too bad you can't have multiple :s on one line :( \$\endgroup\$ – CalculatorFeline May 28 '17 at 5:35
  • \$\begingroup\$ @OliverNi a,b=1,9 does not save any bytes \$\endgroup\$ – Felipe Nardi Batista Jul 12 '17 at 14:40
4
\$\begingroup\$

Dictionary defaults as entries

Say you have an dictionary literal, which I'll denote {...}, and you want to get the value for a key k, with a default of d if k is missing.

You can save two bytes by prepending an entry rather than using get

{k:d,...}[k]
{...}.get(k,d)

Because later entries override earlier ones of the same key, the entry k:d gets overwritten if it appears in the dict, but remains if key k isn't present.

Note that this required writing k twice, which is fine for a variable, but poor when k is an expression.

\$\endgroup\$
4
\$\begingroup\$

Take multi-line input

Use list(iter(input,eof)) to take multi-line input. eof can be any string that you want to stop taking input on if you see it. An example would be eof = ''. The python 2 version is list(iter(raw_input,eof)), however you may want to use sys.stdin.readlines() instead if you have already imported sys.

\$\endgroup\$
  • \$\begingroup\$ list(iter(input,eof)) is shorter by one, you don't need that space. Also worth noting that this is only for Python 3 - Python 2 is 4 bytes longer because raw_input. \$\endgroup\$ – Mego Nov 30 '15 at 3:15
  • \$\begingroup\$ Is shorter than what? \$\endgroup\$ – J Atkin Nov 30 '15 at 3:33
  • \$\begingroup\$ Than what you have posted, because it has an extraneous space. \$\endgroup\$ – Mego Nov 30 '15 at 3:34
  • \$\begingroup\$ Oh, I see. I assume the reader would remove the space though. I will edit it out now. \$\endgroup\$ – J Atkin Nov 30 '15 at 3:38
4
\$\begingroup\$

Find the n'th number meeting a condition

Many sequence challenges ask you to find the n'th number in a sequence of increasing positive integers. When you have a expression p(i) that checks membership, you can do this with the recursive function:

f=lambda n,i=1:n and-~f(n-p(i),i+1)

Note that expression p(i) must give 0 or 1, not just Falsey or Truthy. The outputs are one-indexed, so say for the sequence of primes, it would give

f(1) = 2
f(2) = 3
...

For 0-indexed outputs, shift the base case

f=lambda n,i=1:n+1and-~f(n-p(i),i+1)

The recursive function f=lambda n,i=1:n and-~f(n-p(i),i+1) works by decrementing the required count n each time it gets a hit, and incrementing the output value each time for each value it checks. It might seem weird to redundantly track i, but it's longer to do:

f=lambda n,i=1:n and f(n-p(i),i+1)or~-i

Also compare the natural list strategy (zero-indexed here)

lambda n:[i for i in range(n*n)if p(i)][n]

(You might need a larger bound than n*n.)

\$\endgroup\$
4
\$\begingroup\$

Iterate over adjacent pairs

It's common to want to iterate over adjacent pairs of items in a list or string, i.e.

"golf" -> [('g','o'), ('o','l'), ('l','f')]

There's a few methods, and which is shortest depends on specifics.

Shift and zip

## 47 bytes
l=input()
for x,y in zip(l,l[1:]):do_stuff(x,y)

Create a list of adjacent pairs, by removing the first element and zipping the original with the result. This is most useful in a list comprehension like

sum(abs(x-y)for x,y in zip(l,l[1:]))

You can also use map with a two-input function, though note that the original list is no longer truncated.

## Python 2
map(cmp,l[:-1],l[1:])

Keep the previous

## 41 bytes, Python 3
x,*l=input()
for y in l:do_stuff(x,y);x=y

Iterate over the elements of the list, remembering the element from a previous loop. This works best with Python 3's ability to unpack to input into the initial and remaining elements.

If there's an initial value of x that serves as a null operation in do_stuff(x,y), you can iterate over the whole list.

## 39 bytes
x=''
for y in input():do_stuff(x,y);x=y

Truncate from the front

## 46 bytes
l=input()
while l[1:]:do_stuff(*l[:2]);l=l[1:]

Keep shortening the list and act on the first two elements. This works best when your operation is better-expressed on a length-two list or string than on two values.

Python 3 can do shorter with unpacking. You can shorten to while l: if your operation is harmless on singletons.


I've written these all as loops, but they also lend to a recursive functions. You can also adjust to get cyclic pairs by putting the first element at the end of the list, or as the initial previous-value.

\$\endgroup\$

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.