un problema di ordinamento interlacciato a funky

0

Ho una serie di elementi. Alcuni articoli hanno un numero su entrambi i lati. Chiamerò queste "coppie abbinate". Ho bisogno di ordinare gli elementi tra le coppie abbinate in un modo particolare.

C'è un "da numero" e un "da numerare" Potrebbe esserci più from -> nil di nil-> to o vice-versa. Potrebbe anche esserci NESSUN oggetto tra le coppie abbinate.

Puoi presumere che i numeri saranno sempre essere ordinati all'interno della loro colonna. Per esempio. Dai numeri passerà da 1 a x crescente e ai numeri andrà da 1 a x crescente. Potrebbe esserci nil s inserito comunque.

# I have this
#   v from number
#          v to number
[
    [nil,  1],
    [1,    2],  # a matched pair
    [2,    nil],
    [3,    nil],
    [4,    nil],
    [5,    nil],
    [nil,  3], # note that there are more 
    [nil,  4], # nil -> to number than 
    [nil,  5], # from number -> nil
    [nil,  6],
    [nil,  7], 
    [6,    8],  # another matched pair
    [7,    9],  # nothing in between
    [8,    nil],# no nil->to number to pair it with
    [9,    10]
]

Devo trasformarlo in questo. Siamo quasi, ma non abbastanza interleaving gli elementi da ogni colonna.

[
    [nil,  1],
    [1,    2],
    [2,    nil],
    [nil,  3],
    [3,    nil],
    [nil,  4],
    [4,    nil],
    [nil,  5],
    [5,    nil],
    [nil,  6],
    [nil,  7],
    [6,    8],
    [7,    9],
    [8,    nil],
    [9,    10]
]

Informazioni aggiuntive che potrebbero essere utili o meno,

Questi numeri rappresentano linee in due documenti. Nell'esempio sopra, il testo sulla riga 2 nel documento "da" non è stato trovato in il documento "a". È stato sostituito dal testo sulla riga 3 (nel documento "a"). Il testo sulla riga 3 nel documento "a" non lo era trovato nel documento "da" così. Quindi, 2 - > nil (due sono andati via) nil- > 3 (tre è stato aggiunto).

    
posta masukomi 04.05.2016 - 16:03
fonte

4 risposte

2

Per garantire l'ordine crescente in entrambe le colonne possiamo confrontare per colonna quando non c'è nil e per valore massimo quando c'è:

.sort { |(a0, a1), (b0, b1)|
  if [a0, b0].none?(&:nil?)
    a0 <=> b0
  elsif [a1, b1].none?(&:nil?)
    a1 <=> b1
  else
    a0, a1, b0, b1 = [a0, a1, b0, b1].map(&:to_i)
    [[a0, a1].max, a0, a1] <=> [[b0, b1].max, b0, b1]
  end
}
  1. Confronta due elementi alla volta
  2. Se le colonne di sinistra sono entrambi numeri interi positivi, usa quello per ordinare.
    • funziona perché se entrambi hanno numeri, allora il numero corretto è sempre corretto rispetto a sinistra, quindi l'ordinamento a sinistra ti dà il risultato giusto.
  3. Se le colonne di destra sono entrambi numeri interi positivi, utilizzale per ordinare.
    • sappiamo che non è una coppia abbinata ed entrambi i numeri lasciati sono nulli ed entrambi i diritti sono paragonabili quindi ...
  4. Converti tutti i nils in qualcosa con cui possiamo lavorare ( .to_i li rende zero).
  5. Altrimenti, crea matrici da ordinare, con il primo elemento di ogni matrice che è il numero non nullo (non zero a questo punto). .max è solo un modo semplice per ottenere quello non zero.
risposta data 04.05.2016 - 17:23
fonte
1

La maggior parte delle lingue consente di fornire una funzione di confronto personalizzata all'ordinamento. Vedi Java Comparator

Un utilizzo di un comparatore personalizzato, ad esempio, consiste nell'ordinamento basato su due attributi (primario e secondario) con un solo ordinamento. Un comparatore per questo prima confronterà gli attributi primari, quindi solo se sono uguali, controllerà l'attributo secondario.

Un comparatore personalizzato per il tuo tipo dovrebbe prima ottenere un valore primario per ciascuno dei due elementi da confrontare. Questo valore primario potrebbe essere il primo numero dell'intervallo o, se necessario, l'ultimo numero dell'intervallo. Quindi, se i valori primari sono uguali, il comparatore passerebbe a testare un valore secondario, ottenuto similmente dall'ultimo intervallo con un comportamento appropriato quando zero (ad esempio valore massimo o qualcosa).

    
risposta data 04.05.2016 - 17:25
fonte
-1

Ah ... penso di avere una risposta. Ecco un approccio a due passaggi (chiamando ogni coppia [x, y] ).

  1. Seleziona tutte le coppie in cui x non è nullo. Ordinali per x . Chiama l'elenco risultante s .
  2. Seleziona tutte le coppie in cui x è nullo. Inseriscili in s nei luoghi appropriati (non sono sicuro di come determini i posti appropriati, comunque).

Ti aiuta?

    
risposta data 04.05.2016 - 17:10
fonte
-1
# ruby syntax

 def compare_them (obj1, obj2)
  if obj1[0].nil? 
    if !obj2[0].nil?
      return obj1[1] <=> obj2[0]
    else  
      if obj2[1].nil?
        if obj1[1] == obj2[0]
          return -1
        else 
          return obj1[1] <=> obj2[0]
        end
      else
        return obj1[1] <=> obj2[1]
      end
    end
  else
    if obj2[0].nil?
      if obj1[1].nil?
        if obj1[0] == obj2[1]
          return 1
        else 
          return obj1[0] <=> obj2[1]
        end
      else
        return obj1[1] <=> obj2[1]
      end
    else
      return obj1[0] <=> obj2[0]  
    end
  end
end

foo = [[nil, 1],
       [1, 2],
       [2, nil],
       [3, nil],
       [4, nil],
       [5, nil],
       [nil, 3],
       [nil, 4],
       [nil, 5],
       [nil, 6],
       [nil, 7],
       [6, 8],
       [7, 9],
       [8, nil],
       [9, 10]]

foo.sort { |a1,a2| compare_them(a1, a2) }
    
risposta data 05.05.2016 - 02:36
fonte

Leggi altre domande sui tag