2010-10-16 20 views
9

Tengo una larga tupla comoSpliting un largo tupla en tuplas más pequeños

(2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10) 

y yo estoy tratando de dividirlo en una tupla de tuplas como

((2, 2, 10, 10), (344, 344, 45, 43), (2, 2, 10, 10), (12, 8, 2, 10)) 

Soy nuevo en Python y estoy no muy bueno con las tuplas o (2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10) r listas. Mi amigo dijo que debería dividirlo, pero simplemente no puedo obtenerlo -_-

Necesito dividir la tupla en tuplas con 4 elementos que luego usaré un rectángulo para dibujar en una imagen con PIL.

+1

Sería bueno si explicaras lo que estás haciendo con la tupla que requiere que se divida. Probablemente obtendrá respuestas más útiles e informativas de esa manera. – JoshD

+5

@JohnD: FWIW, no creo que esto sea tan complejo o inusual como para necesitar un gran contexto. –

Respuesta

9

bien hay una cierta expresión idiomática para ello:

def grouper(n, iterable): 
    args = [iter(iterable)] * n 
    return zip(*args) 

t = (2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10) 
print grouper(4, t) 

Pero este tipo de complicado de explicar. Una versión un poco más general de esto se enumera en the itertools receipes.

También puede cortar la tupla ti mismo

parts = (t[0:4], t[4:8], t[8:12], t[12:16]) 

# or as a function 
def grouper2(n, lst): 
    return [t[i:i+n] for i in range(0, len(t), n)] 

que es probablemente lo que significaba su amigo.

+4

No llamaría eso idiomático, nunca lo había visto antes, y me llevó varios segundos descubrir qué estaba pasando. No hay nada de malo en esto, pero por supuesto, asegúrese de documentar y documentar. –

+0

Gracias funcionó: D – giodamelio

+0

Por cierto, recomiendo 'return itertools.izip (* args)', por lo que esto funciona correctamente con grandes iteradores al no tratar de consumir todo el iterador. Una buena entrada de prueba es 'itertools.cycle ((1,2,3))'. –

0

Otra respuesta posible (utilizando un generador):

oldTuple = (2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10) 
newTuple = tuple(oldTuple[x:x+4] for x in range(0, len(oldTuple), 4)) 
1
>>> atup 
(2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10) 
>>> [ atup[n:n+4] for n,i in enumerate(atup) if n%4==0 ] 
[(2, 2, 10, 10), (344, 344, 45, 43), (2, 2, 10, 10), (12, 8, 2, 10)] 
+0

Like @ ghostdog74 responde porque, incluso si la última tupla tiene 1 elemento, se convierte en la última tupla con 1 elemento, otras soluciones simplemente dejan la última tupla de 1 elemento. – NullException

0

que había escrito una función tal como GIST algún tiempo atrás, disponible en http://gist.github.com/616853

def split(input_list,num_fractions=None,subset_length=None): 
    '''                                 
    Given a list/tuple split original list based on either one of two parameters given but NOT both,         
    Returns generator                             
    num_fractions : Number of subsets original list has to be divided into, of same size to the extent possible.      
        In case equilength subsets can't be generated, all but the last subset            
        will have the same number of elements.                    
    subset_length : Split on every subset_length elements till the list is exhausted.             

    ''' 
    if not input_list: 
     yield input_list #For some reason I can't just return from here : return not allowed in generator expression     
    elif not bool(num_fractions)^bool(subset_length): #Will check for both the invalid cases, '0' and 'None'.. Oh Python :)   
     raise Exception("Only one of the params : num_fractions,subset_length to be provided") 
    else: 
     if num_fractions: #calcluate subset_length in this case                   
      subset_length = max(len(input_list)/num_fractions,1) 

     for start in xrange(0,len(input_list),subset_length): 
      yield input_list[start:start+subset_length] 



>> list(list_split.split((2, 2, 10, 10, 344, 344, 45, 43, 2, 2, 10, 10, 12, 8, 2, 10),subset_length=4)) 
[(2, 2, 10, 10), (344, 344, 45, 43), (2, 2, 10, 10), (12, 8, 2, 10)] 

El código es más largo que las soluciones dadas anteriormente, pero cubren todas las condiciones de división de secuencia posibles.

+0

Gracias pero el anterior funciona bien. guardando el código ya que podría ser un uso completo en el lugar correcto. – giodamelio

Cuestiones relacionadas