2016-06-09 93 views
8

usando lo strumento itertools, ho tutte le possibili permutazioni di una determinata lista di numeri, ma se la lista è la seguente:Come generare permutazioni di una lista senza "spostare" gli zeri. in Python

List=[0,0,0,0,3,6,0,0,5,0,0] 

itertools non "sa" che l'iterazione gli zeri è sprecato lavoro , per esempio, i seguenti iterazioni appariranno nei risultati:

List=[0,3,0,0,0,6,0,0,5,0,0] 

List=[0,3,0,0,0,6,0,0,5,0,0] 

essi sono uguali ma itertools prende solo il primo zero (per esempio) e lo sposta al quarto posto nella lista e viceversa.

La domanda è: come posso ripetere solo alcuni numeri selezionati e lasciato da solo altri come zero? può essere con o senza itertools.

+0

Usa qualcosa come 'output2 = list (set (output))', dove 'output' è quello che hai ottenuto da' itertools'. –

+0

Ho bisogno di iterare dei numeri in tutte le posizioni all'interno della lista, lasciando da parte lo zero. –

+1

e ci sei. (il mio nuovo, terzo approccio, risposta) – jsbueno

risposta

3

voila - funziona ora - dopo aver ottenuto le permutazioni sulla "carne", ho ulteriormente ottenere tutte le possibili combnations per le posizioni dei "0" e la resa una permutazione per ogni possibile set di "0 posizioni" per ogni permutazione dei non-0:

from itertools import permutations, combinations 

def permut_with_pivot(sequence, pivot=0): 
    pivot_indexes = set() 
    seq_len = 0 
    def yield_non_pivots(): 
     nonlocal seq_len 
     for i, item in enumerate(sequence): 
      if item != pivot: 
       yield item 
      else: 
       pivot_indexes.add(i) 
     seq_len = i + 1 

    def fill_pivots(permutation): 
     for pivot_positions in combinations(range(seq_len), len(pivot_indexes)): 
      sequence = iter(permutation) 
      yield tuple ((pivot if i in pivot_positions else next(sequence)) for i in range(seq_len)) 

    for permutation in permutations(yield_non_pivots()): 
     for filled_permutation in fill_pivots(permutation): 
      yield filled_permutation 

(ho usato parola chiave di Python 3 "non locale" - se si è ancora in Python 2.7, si dovrà prendere un altro approccio, come fare seq_len essere una lista con un singolo elemento si può quindi repplace su quello interno funzione)

il mio secondo tentativo (il lavoro è in realtà il 3 °)

Questo è un approccio ingenuo che continua a una cache delle permutazioni già "visto" - consente di risparmiare sul lavoro svolto da ciascun permutazione ma non il lavoro per generare tutte le possibili permutazioni:

from itertools import permutations 

def non_repeating_permutations(seq): 
    seen = set() 
    for permutation in permutations(seq): 
     hperm = hash(permutation) 
     if hperm in seen: 
      continue 
     seen.add(hperm) 
     yield permutation 
+0

Io uso Python 3. Ci proverò, grazie. –

+0

sì, mantiene 0 fisso! :) –

+1

ora è necessario dare un'occhiata alle partizioni di n dove n è il numero di zeri nell'elenco originale. Anche il numero di elementi diversi da zero (k) è importante in quanto definiscono i tipi di partizione ammessi. ad esempio se k = 3 come nell'esempio sopra ogni partizione può essere espressa come somma di k + 1 valori ma non di più. –

0

Aggiungere ciascun risultato a un elenco. Ora dovrete ogni combinazione possibile e poi fare la seguente:

list(set(your_big_list)) 

Set sarà restringere l'elenco verso il basso per solo le permutazioni unici. Non sono del tutto sicuro se questo è il problema che stai cercando di risolvere o sei preoccupato per le prestazioni. Indipendentemente appena fatto un conto così ho pensato di provare a contribuire con qualcosa

+1

l'unico problema che vedo con il vostro approccio è che è computazionalmente inefficiente. Ci deve essere un modo migliore. –

+0

sì, il problema che sto cercando di risolvere è per prestazioni e velocità. usando grandi liste di numeri, per esempio di 30 o più, il programma lavora troppo tempo, e molto lavoro è sprecato, ergo non efficiente. –

+0

'Set' e' List' non sono nemmeno built-in Python.Forse intendevi 'list' e' set' – jsbueno

0

vostre domande è chiaro, ma se si sta cercando di elencare le permutazioni senza avere 0 nell'output, si può fare come segue:

from itertools import permutations 
def perms(listy): 
    return permutations([i for i in listy if i!=0]) 
+1

Non penso che questo sia ciò che vuole ma questo può essere la base per questo. ora puoi impregnare le tue permutazioni con 0 per generare ancora più combinazioni ognuna delle quali ha la lunghezza dell'elenco originale ☺ –

+1

Ho bisogno dello 0 nell'output ma non ho bisogno che faccia parte della permutazione. questo per evitare duplicati di output e perdita di lavoro della CPU. forse posso creare una lista base di zeri e quindi inserire i numeri permutati in essa? –