Come combinare N array non confrontabili fino a un limite di output in modo corretto?

2

Dato N matrici non confrontabili di diverse dimensioni, qual è il metodo migliore per combinarle in un unico array di output?

Poiché gli array di input non sono confrontabili, è necessaria una metrica per rappresentare la frequenza con cui il valore in cima alla matrice in questione viene aggiunto all'array di output. Chiamiamo weight e lascia che sia un valore arbitrario da 1 a 10 .

Ecco un esempio di serie di dati con pesi:

numbers = [1, 2, 3, 4, 5]
numbers_weight = 3

books = ['The Lord of the Rings', 
         'The Hitchhikers Guide to the Galaxy', 
         'Enders Game',
         '1984']
books_weight = 5

words = ['polar', 'fiendish', 'percussive']
words_weight = 10

Una soluzione ingenua potrebbe generare un numero casuale e quindi chiedere ad ogni array se passa o fallisce in base al suo peso. Se passa, aggiungilo alla fine della matrice di output. Quindi genera un nuovo numero casuale e ricomincia da capo fino a quando non viene raggiunto un limite massimo.

Ecco la soluzione ingenua che agisce sui dati di esempio:

def join_arrays(arrays, weights, weight_min, weight_max, output_limit):
    output = []
    while True:
        rnd = random.randint(weight_min, weight_max)
        for i in range(len(arrays)):
            if rnd <= weights[i] and len(arrays[i]) > 0:
                output.append(arrays[i].pop(0))
                if len(output) >= output_limit:
                    return output

Ed ecco come viene chiamata la funzione, usando ancora i dati di esempio:

arrays = [numbers, books, words]
weights = [numbers_weight, books_weight, words_weight]

random.seed(time.time())
output = join_arrays(arrays, weights, 1, 10, 6)

Il problema che ho con questo tipo di implementazione in stile round robin è che se la dimensione di arrays è enormemente maggiore di output_limit , quelli verso il retro di arrays appariranno meno frequentemente di quanto il loro peso sarebbe suggerire, o non farlo affatto, perché ci saranno casi in cui semplicemente non è stato chiesto se passano, e quindi non aggiunti a output .

C'è una soluzione a questo problema che consente a tutti gli array di input all'interno di arrays di essere chiesti se passano o falliscono, quindi sono equi, pur consentendo una output_limit ?

L'uso di pesi è appropriato anche per questo tipo di combinazione?

    
posta zzelman 18.03.2016 - 05:43
fonte

1 risposta

1

Sembra che la cosa che vuoi fare sia questa:

  1. Scegli un array dalla lista ponderata di array non vuoti
  2. Inserisci un valore da tale array e aggiungilo all'array di output
  3. Ripeti alcune volte

Sembra che tu abbia qualche problema nel fare il punto 1 in modo corretto. Il mio suggerimento è di appiattire la lista ponderata in una lista contenente ogni array < array-weight > volte e scegli abbastanza da quello.

Nel codice qui sotto, ripeto ogni array < weight > volte e aggiungerlo all'elenco generale degli array. Nota che questo approccio crea una lista di N riferimenti agli array originali. In questo modo, quando apri uno qualsiasi dei riferimenti, lo stai facendo per l'unico oggetto che li supporta tutti.

Per motivi di sicurezza, elimino anche la lista se quella scelta a caso era vuota. Questo mi copre nel caso limite in cui il numero di elementi richiesti è superiore al numero totale di elementi negli elenchi di input. In tal caso, finisco per restituire una fusione semi-mescolata di tutti gli elementi negli array di input.

def join_arrays(arrays, weights, output_limit):
    data = []
    for array, weight in zip(arrays, weights):
        data.extend([array]*weight)
    output = []
    while data and len(output) < output_limit:
        value = random.choice(data)
        if value:
            output.append(value.pop())
        else:
            data.remove(value)
    return output
    
risposta data 19.04.2016 - 04:52
fonte

Leggi altre domande sui tag