2012-07-13 15 views
11

Ho bisogno di aiuto con qualcosa che sembra semplice ma mi confonde. Cercando di scrivere un metodo di corrispondenza fuzzy che gestisca le differenze di formato tra il valore calcolato in base alle esigenze e che sono effettivamente disponibili da un elenco di selezione.come trovare l'elemento di corrispondenza migliore nella matrice di numeri?

Il valore (prezzo di esercizio dell'opzione) è sempre un Float calcolato come 85.0 o Int.

L'array contiene numeri in forma di stringa, imprevedibili ne incrementano o se saranno mostrati arrotondato a qualche decimale (compresi gli zeri supplementari come 5.50) o senza decimale (come 85), es .:

select_list = ["77.5", "80", "82.5", "85", "87.5", "90", "95", "100", "105"] 

Non sono sicuro di come scrivere una semplice riga o due di codice che restituirà l'elemento di corrispondenza più vicino (in base al valore numerico) come appare nell'array. Per esempio, se select_list.contains? 85.0 restituito "85"

In realtà, le scelte di selezione provengono da un oggetto Watir::Webdriver browser.select_list(:id, "lstStrike0_1") HTML il cui testo visibile (non il valore HTML) sono quei numeri; forse c'è un modo più diretto per chiamare semplicemente browser.select_list(:id, "lstStrike0_1").select X senza dover capire in Watir come convertire tutte quelle scelte in un array Ruby?

+0

Un'altra domanda http://stackoverflow.com/q/6358860/1069375 mi ha illuminato come convertire facilmente l'elenco_selezione Watir nell'array necessario: 'selectContent = browser.select_list (: id," lstStrike0_1 "). options.map (&: text)' – Marcos

risposta

20
xs = ["77.5", "80", "82.5", "85", "87.5", "90", "95", "100", "105"] 
xs.min_by { |x| (x.to_f - 82.4).abs } 
#=> "82.5" 
+0

Il modo più conciso che vedo. Per i miei scopi la soluzione completa combinata in una riga era '$ browser.select_list (: id," lstStrike0_0 "). Select (strikelist = $ browser.select_list (: id," lstStrike0_0 "). Options.map (&: text)) .min_by {| x | (x.to_f - sigitem [: strikel]). abs} ' – Marcos

5

Io non sono un programmatore rubino quindi questo potrebbe non essere il modo migliore per farlo

def select_closest(list, target)        
    return (list.map {|x| [(x.to_f - target).abs, x]}).min[1] 
end                

select_list = ["77.5", "80", "82.5", "85", "87.5", "90", "95", "100", "105"] 

puts select_closest(select_list, 81) # yields 80 
+0

I esp. ad esempio, hai considerato valori numerici inesatti (81 vs 80 più vicini) anche se non l'ho menzionato esplicitamente, ma è probabile che si verifichi. Grazie! – Marcos

Problemi correlati