Pregunta

Soy algo nuevo a Ruby y aunque me parece que es un lenguaje muy intuitivo que estoy teniendo algunas dificultades para la comprensión de cómo se comportan los valores de retorno implícita.

Estoy trabajando en un pequeño programa para grep registros de Tomcat y generar archivos CSV delimitado por tuberías a partir de los datos pertinentes. Aquí está un ejemplo simplificado que estoy usando para generar las líneas de una entrada de registro.

class LineMatcher
  class << self
    def match(line, regex)
      output = ""
      line.scan(regex).each do |matched|
        output << matched.join("|") << "\n"
      end
      return output
    end        
  end
end


puts LineMatcher.match("00:00:13,207 06/18 INFO  stateLogger - TerminationRequest[accountId=AccountId@66679198[accountNumber=0951714636005,srNumber=20]",
                       /^(\d{2}:\d{2}:\d{2},\d{3}).*?(\d{2}\/\d{2}).*?\[accountNumber=(\d*?),srNumber=(\d*?)\]/)

Al ejecutar el código que vuelva el siguiente, que es lo que se espera al devolver explícitamente el valor de la producción.

00:00:13,207|06/18|0951714636005|20

Sin embargo, si cambio LineMatcher a la siguiente y no regreso explícita de salida:

    class LineMatcher
      class << self
        def match(line, regex)
          output = ""
          line.scan(regex).each do |matched|
            output << matched.join("|") << "\n"
          end
        end        
      end
    end

A continuación, me sale el siguiente resultado:

00:00:13,207
06/18
0951714636005
20

Obviamente, este no es el resultado deseado. Se siente como que debería ser capaz de deshacerse de la variable de salida, pero no está claro que el valor de retorno está viniendo. También, alguna otra sugerencia / mejoras para facilitar la lectura son bienvenidos.

¿Fue útil?

Solución

Cualquier declaración en rubí devuelve el valor de la última expresión evaluada. Es necesario conocer la implementación y el comportamiento del método más utilizado con el fin de saber exactamente cómo su programa actuará.

#each devuelve la colección que repitan ciertos sucesivamente. Dicho esto, el siguiente código devolverá el valor de line.scan (expresión regular).

line.scan(regex).each do |matched|
  output << matched.join("|") << "\n"
end

Si desea devolver el resultado de la ejecución, puede utilizar map, que funciona como each pero devuelve la colección modificada.

class LineMatcher
  class << self
    def match(line, regex)
      line.scan(regex).map do |matched|
        matched.join("|")
      end.join("\n") # remember the final join
    end        
  end
end

Existen varios métodos útiles que puede utilizar dependiendo de su caso muy específico. En éste es posible que desee utilizar inject a menos que el número de resultados devueltos por scan es alta (trabajando en matrices luego fusionarlos es más eficiente que trabaja en una sola cadena).

class LineMatcher
  class << self
    def match(line, regex)
      line.scan(regex).inject("") do |output, matched|
        output << matched.join("|") << "\n"
      end
    end        
  end
end

Otros consejos

En el rubí el valor de retorno de un método es el valor devuelto por la última declaración. Usted puede optar por tener un rendimiento explícito también.

En el ejemplo, el primer fragmento de código devuelve la cadena output. El segundo fragmento sin embargo devuelve el valor devuelto por la each método (que es ahora el último stmt), que resulta ser una matriz de coincidencias.

irb(main):014:0> "StackOverflow Meta".scan(/[aeiou]\w/).each do |match|
irb(main):015:1* s << match
irb(main):016:1> end
=> ["ac", "er", "ow", "et"]

Actualización: No obstante que aún no explica su salida en una sola línea. Creo que es un error de formato, se debe imprimir cada uno de los partidos en una línea diferente porque así es como puts imprime una matriz. Un poco de código lo puede explicar mejor que yo ..

irb(main):003:0> one_to_three = (1..3).to_a
=> [1, 2, 3]
irb(main):004:0> puts one_to_three
1
2
3
=> nil

Personalmente, creemos que el método con el rendimiento explícito más legible (en este caso)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top