Unione di elenchi ordinati (senza funzione di confronto)

-1

Ho alcuni elenchi di elementi (che probabilmente non hanno necessariamente elementi comuni). Gli elenchi sono noti per essere ordinati, ma non hanno una funzione di confronto (sono stati inseriti manualmente nel sistema in ordine). Mi piacerebbe combinare queste liste in una lista contenente tutti gli elementi che sono in un ordine ragionevole dati quelli esistenti.

Ovviamente ci sono casi limite e decisioni da prendere - non sono troppo preoccupato per le specifiche, ma piuttosto mi piacerebbe un approccio generale per affrontare il problema. Ovviamente se le due liste non hanno nulla in comune, non c'è molto da fare se non accodare l'una all'altra, ma ciò non accadrà molto.

Ad esempio:

l1 = ['Task A', 'Task B', 'Task C', 'Task D']
l2 = ['Task B', 'Task B2', 'Task D', 'Task G']
l3 = ['Task A', 'Task C', 'Task E', 'Task D']
result = ['Task A', 'Task B', 'Task B2', 'Task C', 'Task E', 'Task D', 'Task G']

Ancora una volta, mi rendo conto che non esiste una soluzione perfetta e l'output non è mission critical, voglio solo che sia ragionevolmente ordinato nella maggior parte dei casi. Qualsiasi aiuto sarebbe apprezzato.

    
posta The Bearded Templar 03.11.2015 - 19:50
fonte

2 risposte

5

Questo è un problema ben definito con una soluzione deterministica. Puoi pensare a ciascuna lista come parte di un grafico aciclico diretto :

Quindi,lacostruzionediunordineunitoèsemplicementeunaquestionediutilizzodiunodeibennotialgoritmipertrovareun ordinamento topologico . Più somiglianze hai tra le liste, meno pochi tipi topologici validi avrai. Se non ci sono elementi in comune, l'ordinamento topologico funzionerà anche per quel caso. Elencherà tutti i modi possibili per combinare le tre liste. Devi solo scegliere quello che ti sta meglio esteticamente.

    
risposta data 03.11.2015 - 20:37
fonte
1

Se non hai letteralmente nessuna funzione di confronto, allora l'unica opzione ragionevole è quella di scegliere lo stesso ordine ogni volta:

one = [1,2,3]
two = [4,5,6]
three = [7,8,9]

merge(one, two, three) == [1,4,7,2,5,8,3,6,9]

Se c'è un ordine e gli oggetti possono essere confrontati per l'uguaglianza, ma non puoi codificare l'ordine in modo esplicito, puoi tenere traccia di quante volte li hai visti in determinati ordini e usarli per generare euristiche.

Puoi creare una cronologia su cui basare le ipotesi memorizzando tutte le visite

Penso che questi tipi di dati e algebra (espressi in pseudo-scala) servano bene a questo scopo.

// How many times a given item has been seen
type ItemCount = Map[Item, Int]

// NB ItemHistory forms a commutative monoid with zero as empty maps and mappend adding the counts together
case class ItemHistory(itemsSeenBefore: ItemCount, itemsSeenAfter: ItemCount)

// Fold over a list of input items and generate history for each one, storing the count of all items seen before and after
List[Item] => Map[Item, ItemHistory]

// Update your counts with more data
(Map[Item, ItemHistory], List[Item) => Map[Item, ItemHistory]

// Generate an ordering between two items, with a % accuracy.
// Whichever has been seen more often before or after defines the ordering.
// The accuracy is determined by taking the ratio of times that ordering was correct vs the entire history.
(Item, ItemHistory) => (Item, ItemHistory) => (Ordering, Float)

// Apply some cutoff for filtering out inaccurate orderings
(Ordering, Float) => Ordering

Se implementi una classe con metodi lungo quelle linee, puoi usarla per generare euristiche. Poiché ItemHistory è un monoid, puoi facilmente addestrarlo offline con i dati che hai oggi, persistere in ItemHistories in qualsiasi modo conveniente, e quindi aggiornarli continuamente con i nuovi dati di allenamento appena entrati.

    
risposta data 03.11.2015 - 19:54
fonte

Leggi altre domande sui tag