2014-04-22 8 views
14

Ho notato che a partire da Ruby 2.0.0 la classe dell'array ha un metodo bsearch che stavo testando e non sto ottenendo il comportamento che mi aspetterei. Perché restituisce un valore per 2 e 5 ma nil per -1, 1 e 4?Ruby 2.0.0 Array # bsearch behavior

arr_in = [-1, 1, 2, 4, 5] 

arr_in.bsearch { |x| x == 3 } #=> nil 
arr_in.bsearch { |x| x == -1 } #=> nil 
arr_in.bsearch { |x| x == 1 } #=> nil 
arr_in.bsearch { |x| x == 2 } #=> 2 
arr_in.bsearch { |x| x == 4 } #=> nil 
arr_in.bsearch { |x| x == 5 } #=> 5 

risposta

24
arr_in = [-1, 1,2,4,5] 
arr_in.bsearch{ |x| 2 - x } 
#=> 2 
arr_in.bsearch{ |x| -1 - x } 
#=> -1 
arr_in.bsearch{ |x| 3 - x } 
#=> nil 

ricerca binaria usa risultato del blocco come un suggerimento, che parte di array (lato destro o sinistro) dovrebbe essere scelto per la ricerca sulla prossima iterazione. Se il blocco restituisce 0, smetterà di cercare. Se restituisce meno di 0 andrà sinistra altrimenti si va a destra :)

Maggiori informazioni qui http://www.ruby-doc.org/core-2.1.1/Array.html#method-i-bsearch

UPD

Ok, prendiamo il vostro esempio

arr_in = [-1, 1, 2, 4, 5] 
arr_in.bsearch { |x| x == 3 } 

First prendiamo l'elemento intermedio (2) e lo cediamo al blocco. 2 == 3 restituirà false, quindi ci spostiamo sul lato destro dell'array.

Prendiamo elemento centrale di [4, 5] che è 5 e 5 == 3 è false

non v'è alcun elemento a destra, quindi torneremo nil

arr_in = [-1, 1, 2, 4, 5] 
arr_in.bsearch { |x| x == 2 } 

Prima 2 == 2 è true. Andiamo a sinistra.

Elemento centrale di [-1, 1] è 1. 1 == 2 è false. Andiamo a destra.

Non ci sono elementi in [-1, 1] diritto alla 1, così torniamo ultimo ultimo elemento che ha restituito true dichiarazione che è 2

PS: non dimenticate, che l'array deve essere ordinato;)

+0

Si dovrebbe spiegare cosa è successo * nella modalità di ricerca minima *? Come gli esempi di OP sono legati a questo. –

+0

@ArupRakshit Io penso che l'autore stia chiedendo di trovare qualsiasi, no? – fl00r

+0

Io non la penso così .. –

1

trovo più intuitivo per utilizzare l'operatore astronave

array.bsearch {|x| 3 <=> x } 

Basta fare in modo di mettere il x alla destra della nave spaziale.

Questo funziona anche per stringhe e qualsiasi oggetto che sia paragonabile a <=>.