I'm trying to make an "even only" hex grid in Python.
The expected output is
[[(0,0), (2,0), (4,0), (6,0)],
[(1,1), (3,1), (5,1), (7,1)],
[(0,2), (2,2), (4,2), (6,2)],
[(1,3), (3,3), (5,3), (7,3)]]
I was tinkering with this:
>>> [[(x,y) for x in range(7)[::2]] for y in range(4)]
[[(0,0), (2,0), (4,0), (6,0)],
[(0,1), (2,1), (4,1), (6,1)],
[(0,2), (2,2), (4,2), (6,2)],
[(0,3), (2,3), (4,3), (6,3)]]
But the next place I went from there throws an exception:
>>> [[(x,y) for x in xrange(y % 2, 6 + (y % 2))[::2]] for y in range(4)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence index must be integer, not 'slice'
Another way of doing it is the following:
[zip(range(i % 2, 8, 2), (i,) * 4) for i in range(4)]
Swapping out range
for xrange
in this code snippet will not break it. Using the optional step argument on range
is better than getting a full range and slicing it.
Explanation of why slicing xrange failed:
In Python 2.x, calls toxrange
return a special type of xrange object, while calls to range
return ordinary Python lists:
>>> xrange(10)
xrange(10)
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The xrange
version crashed because you can't use slice-syntax with the xrange
objects:
>>> xrange(10)[::2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence index must be integer, not 'slice'
But you can do it with range
, since range
returns a list which supports more operations:
>>> range(10)[::2]
[0, 2, 4, 6, 8]
Still, rather than slicing the returned list from range with a step, I would recommend just using the optional step argument that will work with both range and xrange!