2012-07-13 23 views
11

Necesito ayuda con algo que parece simple pero me confunde. Intenta escribir algún método de coincidencia difusa que resuelva las diferencias de formato entre el valor que se calcula según sea necesario y el que realmente está disponible en una lista de selección.cómo encontrar el mejor elemento coincidente en una matriz de números?

El valor (precio de ejecución de la opción) siempre es un Float calculado como 85.0 o Int.

La matriz contiene números en forma de cadena, impredecibles en cualquier incremento o si van a ser mostrados redondeado a algunos decimal (incluyendo ceros adicionales como 5.50) o no decimal (como 85), por ejemplo .:

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

No estoy seguro de cómo escribir una o dos líneas simples de código que devolverán el elemento coincidente más cercano (por valor numérico) tal como aparece en la matriz. Por ejemplo, si select_list.contains? 85.0 regresaron "85"

En realidad, las opciones de selección provienen de un objeto HTML Watir::Webdriver browser.select_list(:id, "lstStrike0_1") cuyo texto visible (no el valor del HTML) son esos números; tal vez haya una manera más directa de simplemente llamar al browser.select_list(:id, "lstStrike0_1").select X sin tener que descubrir en Watir cómo convertir todas esas opciones en una matriz de Ruby.

+0

Otra pregunta http://stackoverflow.com/q/6358860/1069375 me iluminada cómo Convierta fácilmente Watir select_list en la matriz necesaria: 'selectContent = browser.select_list (: id," lstStrike0_1 "). options.map (&: text)' – Marcos

Respuesta

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

La manera más concisa que veo. Para mis propósitos, la solución completa combinada en una sola línea 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

No soy un codificador de rubí por lo que este podría no ser la mejor manera de hacerlo

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. así consideraba valores numéricos inexactos (81 frente a los 80 más cercanos) aunque no mencioné explícitamente eso, pero es probable que ocurra. ¡Gracias! – Marcos

Cuestiones relacionadas