2012-06-14 21 views
11

Estoy filtrando una matriz en ruby ​​y usando un bloque .select para hacerlo. Las condiciones son lo suficientemente complejas como para que un solo bloque de línea sea espantoso pero no tan grande, por lo que un método diferente parece exagerado. Por lo tanto, quiero usar un bloque multilínea. Sin embargo, no estoy seguro de la sintaxis.Ruby array.select bloque multilínea

filtered_array = base_array.select do |elem| 
    return false if condition1 
    return false if condition2 
    return true 
end 

Lo anterior es claramente incorrecto, ya que return sale del método, no el bloque, pero da una idea de lo que estoy buscando.

También podría utilizar múltiples declaraciones de selección, pero eso parece ofuscar lo que estoy tratando de hacer. Tenga en cuenta que las condiciones anteriores son lo suficientemente complejas que el uso de operadores lógicos para vincularlos resulta en un desastre.

+0

También puede utilizar variables temporales. –

+0

@ Anton ver mi edición por favor. – Kyle

+0

Los bloques en matrices no funcionan con declaraciones de retorno (las devoluciones regresarían del método que contiene el bloque) a menos que sean lambdas, que bloques, por defecto, no lo son. La solución para su caso de uso particular es la que proporcionó Kyle, la general sería una declaración de caso o caso como zetetic provista, y en general, simplemente no use declaraciones de retorno para regresar de bloques, a menos que sepa que van a ser lambdas, o convertirse en métodos. –

Respuesta

20

Lo que queremos es next en lugar de return.

+1

Esto funciona si quiero' return false' pero no si quiero 'return true '. – AntonDelprado

+7

'next' puede tomar un valor, al igual que' return'. 'next (true)' es análogo a 'return (true)'. – rcrogers

6

Edit: Acabo de ver esto: "el uso de operadores lógicos para unirlos genera un lío". ¿Podría proporcionarnos las condiciones reales?

filtered_array = base_array.select do |elem| 
    condition1 && condition2 
end 
+0

Creo que el concepto general requiere una respuesta pero: '| elem | self.array1.include? elem.name' y el otro es un poco más complejo 'elem.name.include? "some string" && self.other_array.include? (elem.name.sub ("some string", "other string")) ' – AntonDelprado

2

parece que esto podría ser manejado con una declaración de caso:

filtered_array = base_array.select do |elem| 
    case 
    when condition1 
    false 
    when condition2 
    false 
    else 
    true 
    end 
end 
1

probablemente debería sólo tiene que utilizar:

next(true) 

Sin embargo, si eso no jive con usted entonces hace esto:

my_array.select do |x| 
    # bool = false ### optional, uncomment this if you prefer 
    if x.id == 1 
    bool = true 
    end 
    bool 
end