tags:

views:

85

answers:

3

So I've got a string of bytes which represents cubes in three dimensions. The coordinates are ordered like this:

[x0y0z0, x0y1z0, x0y2z0, ..., x0y127z0, x0y0z1, x0y1z1, ..., x15y127z15]

I'd like to split this into 128 lists, one for each Y coordinate. This code already does that, but I think inefficiently. Is there some way to split this list based on mod(128) of the index?

From the original code:

col.extend(izip_longest(*[iter(file["Level"]["Blocks"].value)]*128))

That takes quite a while, and I think it should be possible to make something better performing by avoiding the *128 part of this. But zipping is definitely not my strong side, and neither is binary file handling.

+3  A: 
# l = [x0y0z0, ...]
def bucketsofun(l, sp=16):
  r = [[] for x in range(sp)]
  for b, e in itertools.izip(itertools.cycle(r), l):
    b.append(e)
  return r
Ignacio Vazquez-Abrams
Do you have more descriptive names for b and e?
l0b0
`bucket` and `element`, if you prefer.
Ignacio Vazquez-Abrams
A: 

Itertools can do it too:

from itertools import izip, izip_longest, chain

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

# you have something like this
# [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
l = list(chain.from_iterable(range(5) for _ in range(5)))

# you want to put all the 0s, 1s (every 5th element) together
print list(izip(*grouper(5, l)))
# [(0, 0, 0, 0, 0), (1, 1, 1, 1, 1), ... , (4, 4, 4, 4, 4)]
THC4k
+2  A: 

Something like this might be worth trying

L = file["Level"]["Blocks"].value
col += [L[i::128] for i in range(127)]
gnibbler