Método de impresión del calendario -- ruby campo con datetime campo con formatting camp codereview Relacionados El problema

Calendar Print Method


9
vote

problema

Español

Actualmente estoy aprendiendo Ruby y necesito ayuda para editar el código para ser más idiomático. Tengo el método a continuación, podría usar algunos punteros sobre cómo hacer más "rubí": -)

  <?php  class Bills {     private $typeAndServicePaymentIdMap = [         0 => 13,         1 => 4, // water         2 => 1, // electricity         3 => 5, // gas         4 => 2, // landline         5 => 3, // cellphone         6 => 6, // municipality due         7 => 6, // municipality due type 7         9 => [             'default' => 24, // traffic due             '001' => 38, // traffic fine             '002' => 38, // traffic fine         ],     ];      private $logger;      public function __construct(File_Logger $logger)     {         $this->logger = $logger;     }      public function getType($billId)     {         return substr($billId, -2, 1);     }      public function getAmount($paymentId)     {         $paymentId = str_pad($paymentId, 13, '0', STR_PAD_LEFT);         $amount = ltrim(substr($paymentId, 0, 8), '0') . '000';          return $amount;     }      public function getCompanyCode($billId)     {         return substr($billId, -5, 3);     }      public function getPaymentServiceId($billId)     {         $type = $this->getType($billId);          if (key_exists($type, $this->typeAndPaymentServiceIdMap)) {             return $this->calculatePaymentServiceId($type);         } else {             $this->logger->errorLog('Type ' . $type . ' is not defined in the $typeAndPaymentServiceIdMap.');         }     }      private function calculatePaymentServiceId($type)     {         $paymentServiceId = $this->typeAndPaymentServiceIdMap[$type];          if (is_array($paymentServiceId)) {             return $this->createPaymentServiceIdFromCompanyCode($paymentServiceId);         } else {             return $paymentServiceId;         }     }      private function createPaymentServiceIdFromCompanyCode($paymentServiceId)     {         $companyCode = $this->getCompanyCode($billId); // TODO: fix this, we don't have $billId here          if (key_exists($companyCode, $paymentServiceId)) {             return $paymentServiceId[$companyCode];         } else {             return $paymentServiceId['default'];         }     } } 2  
Original en ingles

I'm currently learning Ruby and need help in editing code to be more idiomatic. I have the method below I could use some pointers on how to make more "Ruby" :-)

def print_cal(day_of_week, month_len)   days = %w(Mon Tue Wed Thu Fri Sat Sun)   days.each { |day| print "#{day} " }    puts    day_num = 1   month_started = false   while day_num <= month_len     (1..7).each do |i|       if  day_of_week > i && month_started == false         print '    '       else         month_started = true         print ' ' if day_num < 10         print " #{day_num} " if day_num <= month_len         day_num += 1       end     end     puts   end end 
        
 
 

Lista de respuestas

11
 
vote

Aquí está mi opinión, con las explicaciones a continuación:

  def print_calendar(offset, month_length)   puts "Mon Tue Wed Thu Fri Sat Sun"   dates = [nil] * offset + (1..month_length).to_a   dates.each_slice(7) do |week|     puts week.map { |date| date.to_s.rjust(3) }.join(' ')   end end   
  1. Llamaría al primer parámetro offset en lugar de day_of_week . Por ejemplo, day_of_week7 implicaría que puede usar un 9988777766555443388 como el desplazamiento, pero 99887766555443310 La gama es 0-6, con cero siendo domingo, por lo que no funcionará. Además, con def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 1 Me pregunto si te refieres al nombre de un día, o su número? Ah, y de qué semana estamos hablando? El nombre def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 2 es mucho más genérico, pero eso podría ser algo bueno aquí.
    También he explicado def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 3 y def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 4 por completo. Si bien esos nombres no eran demasiado confusos, no hay razón para saltar algunas letras.

  2. También tenga en cuenta que el desplazamiento se comporta ligeramente diferente de la suya: en su método, el desplazamiento mínimo es 1. Eso tiene sentido si cree que "comienza el 1er día", pero tiene menos sentido si piensas " compensar todo por 1 ". Así que aquí, el desplazamiento mínimo es cero.

  3. def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 5 es un buen método para saber cuándo tiene que imprimir listas de cosas (en cualquier idioma, no solo Ruby). Podría haberlo hecho def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 6 en lugar de sus primeras 3 líneas. Pero el resultado final no sería diferente de simplemente imprimir una cadena de codificación dura, por lo que eso es lo que estamos haciendo aquí en su lugar.

  4. En Ruby, rara vez tiene que usar def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 7 Loops. En general, es más fácil construir y manipular matrices utilizando los métodos incorporados en > def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 8 y los mezclados por el def format_calendar offset, month_length [*1..month_length].unshift(*Array.new(offset)). each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " }.unshift "Mon Tue Wed Thu Fri Sat Sun" end puts format_calendar 2, 31 9 Módulo. (En serio, si está aprendiendo Ruby, vaya a leer todo lo que pueda de esos dos enlaces; Son algunas de las cosas más útiles en Ruby, y lo usará mucho).
    Aquí, estamos construyendo un unshift020 s que es unshift2 Ítems de largo usando la capacidad de Nifty de Ruby para multiplica una matriz por un número . Luego usamos unshift3 Para concatenar esa matriz con una matriz que es solo los números 1 .. 99887766555443324 .
    En otras palabras, unshift5 consiste en cero o más "espacios en blanco" (el desplazamiento) seguido de los números de fecha del mes.

  5. unshift6 debe ser bastante explicativo: pasar por una matriz, x elementos a la vez. En este caso, vamos a través de él 7 artículos a la vez (es decir, una semana), que es lo que necesitamos para cada fila / línea de texto.

  6. Cada uno de estos unshift7 unshift8 unshift9 , a una matriz de cuerdas. Cada en blanco / número se convierte primero a una cadena y luego se acolee con espacios usando 99887766555443330 . Finalmente, esta matriz asignada se une y salida.

y eso es, de verdad.

Llamar def format_calendar offset, month_length [ * %w{Mon Tue Wed Thu Fri Sat Sun}, * Array.new(offset), * (1..month_length), ].each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " } end puts format_calendar 2, 31 1 Imprimirá lo siguiente:

 Mon mar mar miércoles sábado sábado           1 2 3 4 5   6 7 8 9 10 11 12  13 14 15 16 17 18 19  20 21 22 23 24 25 26  27 28 29 30 31 

Sin embargo, sería aún más idiomático dejar que el método simplemente devuelva el texto sin imprimiéndolo. Que se podría hacer así:

  def format_calendar offset, month_length   [     * %w{Mon Tue Wed Thu Fri Sat Sun},     * Array.new(offset),     * (1..month_length),   ].each_slice(7).map{ |week|     week.map{ |date| "%3s" % date }.join " "   } end  puts format_calendar 2, 31 2  

después de lo cual puedes hacer algo como

  def format_calendar offset, month_length   [     * %w{Mon Tue Wed Thu Fri Sat Sun},     * Array.new(offset),     * (1..month_length),   ].each_slice(7).map{ |week|     week.map{ |date| "%3s" % date }.join " "   } end  puts format_calendar 2, 31 3  

para imprimirlo.

Editar: como La respuesta de Naklion señala con razón , sería incluso mejor devolver una matriz de cuerdas (Las líneas individuales de texto). En este caso, puede hacerlo simplemente omitiendo el def format_calendar offset, month_length [ * %w{Mon Tue Wed Thu Fri Sat Sun}, * Array.new(offset), * (1..month_length), ].each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " } end puts format_calendar 2, 31 4 en la última línea del método anterior. Eso le dará datos más estructurados para trabajar, en lugar de un blob de texto.
En cuanto a la impresión, no necesita cambiar nada, ya que agrega automáticamente los breakbs al imprimir una matriz.

 

Here's my take, with explanations below:

def print_calendar(offset, month_length)   puts "Mon Tue Wed Thu Fri Sat Sun"   dates = [nil] * offset + (1..month_length).to_a   dates.each_slice(7) do |week|     puts week.map { |date| date.to_s.rjust(3) }.join(' ')   end end 
  1. I'd call the first parameter offset rather than day_of_week. For one, day_of_week would seem to imply that you can use a Date object's wday as the offset, but wday's range is 0-6, with zero being Sunday, so that won't work. Also, with day_of_week I wonder if you mean a day's name, or its number? Oh, and which week are we talking about? The name offset is a lot more generic, but that might be a good thing here.
    I've also spelled out print_calendar and month_length entirely. While those names weren't too confusing, there's no reason to skip a few letters.

  2. Also note that the offset behaves slightly different from yours: In your method, the minimum offset is 1. That makes sense if you think "start on the 1st day", but it makes less sense if you think "offset everything by 1". So here, the minimum offset is zero.

  3. Array#join is a nice method to know when you have to print lists of stuff (in any language, not just Ruby). You could have done puts %w(Mon Tue Wed Thu Fri Sat Sun).join(' ') instead of your first 3 lines. But the end result would be no different than simply printing a hard-coded string, so that's what we're doing here instead.

  4. In Ruby, you rarely have to use while loops. Generally, it's easier to construct and manipulate arrays using the built-in methods in Array and those mixed-in by the Enumerable module. (Seriously, if you're learning Ruby, go read as much as you can from those two links; it's some the most useful stuff in Ruby, and you'll be using it a lot.)
    Here, we're constructing a dates array of nils that's offset items long by using Ruby's nifty ability to multiply an array by a number. Then we use + to concatenate that array with an array that's just the numbers 1..month_length.
    In other words, dates consists of zero or more "blanks" (the offset) followed by the date numbers of the month.

  5. each_slice should be fairly self-explanatory: Go through an array, X items at a time. In this case we go through it 7 items at a time (i.e. a week), which is what we need for each row/line of text.

  6. Each of these weeks are just arrays of nils and/or numbers, so we convert each of them, using map, to an array of strings. Each blank/number is first converted to a string, and then padded with spaces using rjust. Finally, this mapped array is joined and output.

And that's it, really.

Calling print_calendar(2, 31) will print the following:

 Mon Tue Wed Thu Fri Sat Sun           1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31 

However, it'd be even more idiomatic to let the method simply return the text without printing it. That could be done like so:

def format_calendar(offset, month_length)   lines = [ "Mon Tue Wed Thu Fri Sat Sun" ]   dates = [nil] * offset + (1..month_length).to_a   dates.each_slice(7) do |week|     lines << week.map { |date| date.to_s.rjust(3) }.join(' ')   end   lines.join("\n") end 

After which you can do something like

puts format_calendar(2, 31) 

to print it.

Edit: As Naklion's answer rightly points out, it'd be even nicer to return an array of strings (the individual lines of text). In this case, you can do so by simply omitting the .join("\n") on the last line of the method above. That'll give you more structured data to work with, instead of a text blob.
As for printing, you don't need to change anything, since puts automatically adds linebreaks when printing an array.

 
 
         
         
4
 
vote
vote
La mejor respuesta
 
  1. Prefiero devolver la matriz de cadenas que en todo el texto: esto da la capacidad de hacer una vuelta o incluso las líneas inversas
  2. me desharía totalmente de las variables de temperatura y sus tareas
  3. Yo usaría otro enfoque para interpolar el número en cadena: 9988777665544330

y algunos otros trucos:

  def format_calendar offset, month_length   [*1..month_length].unshift(*Array.new(offset)).     each_slice(7).map{ |week|       week.map{ |date| "%3s" % date }.join " "     }.unshift "Mon Tue Wed Thu Fri Sat Sun" end  puts format_calendar 2, 31   

o si encuentra unshift Ugly, intente esto, pero tiene una interpolación inútil para los títulos de los días de semana:

  def format_calendar offset, month_length   [     * %w{Mon Tue Wed Thu Fri Sat Sun},     * Array.new(offset),     * (1..month_length),   ].each_slice(7).map{ |week|     week.map{ |date| "%3s" % date }.join " "   } end  puts format_calendar 2, 31   
 
  1. I would rather return array of strings than the whole text -- this gives ability to loop over or even reverse lines
  2. I would totally get rid of temp variables and their assignments
  3. I would use even another approach to interpolate number into string: "%3s" % date

And some other tricks:

def format_calendar offset, month_length   [*1..month_length].unshift(*Array.new(offset)).     each_slice(7).map{ |week|       week.map{ |date| "%3s" % date }.join " "     }.unshift "Mon Tue Wed Thu Fri Sat Sun" end  puts format_calendar 2, 31 

Or if you find unshift ugly, try this, but it does pointless interpolation for weekday titles:

def format_calendar offset, month_length   [     * %w{Mon Tue Wed Thu Fri Sat Sun},     * Array.new(offset),     * (1..month_length),   ].each_slice(7).map{ |week|     week.map{ |date| "%3s" % date }.join " "   } end  puts format_calendar 2, 31 
 
 
   
   
3
 
vote

Para más rubí idiomático,

  • Uso def format_calendar offset, month_length [ * %w{Mon Tue Wed Thu Fri Sat Sun}, * Array.new(offset), * (1..month_length), ].each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " } end puts format_calendar 2, 31 6 en lugar de def format_calendar offset, month_length [ * %w{Mon Tue Wed Thu Fri Sat Sun}, * Array.new(offset), * (1..month_length), ].each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " } end puts format_calendar 2, 31 7 para emitir una nueva línea.
  • Para que suceda, use def format_calendar offset, month_length [ * %w{Mon Tue Wed Thu Fri Sat Sun}, * Array.new(offset), * (1..month_length), ].each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " } end puts format_calendar 2, 31 8 y def format_calendar offset, month_length [ * %w{Mon Tue Wed Thu Fri Sat Sun}, * Array.new(offset), * (1..month_length), ].each_slice(7).map{ |week| week.map{ |date| "%3s" % date }.join " " } end puts format_calendar 2, 31 39 .
  • construir sus semanas usando def print_calendar(offset, month_length) puts "Mon Tue Wed Thu Fri Sat Sun" dates = [nil] * offset + (1..month_length).to_a dates.each_slice(7) do |week| puts week.map { |date| date.to_s.rjust(3) }.join(' ') end end 0 .

Además, debe usar def print_calendar(offset, month_length) puts "Mon Tue Wed Thu Fri Sat Sun" dates = [nil] * offset + (1..month_length).to_a dates.each_slice(7) do |week| puts week.map { |date| date.to_s.rjust(3) }.join(' ') end end 1 para asegurarse de que cada celda esté formateada en el mismo ancho. Que funciona para los encabezados, el relleno en blanco, las fechas de un dígito y las fechas de dos dígitos.

  def print_calendar(offset, month_length)   puts "Mon Tue Wed Thu Fri Sat Sun"   dates = [nil] * offset + (1..month_length).to_a   dates.each_slice(7) do |week|     puts week.map { |date| date.to_s.rjust(3) }.join(' ')   end end 2  
 

For more idiomatic Ruby,

  • Use puts instead of print to output a newline.
  • To make that happen, use map and join.
  • Construct your weeks using Enumerable#each_slice.

In addition, you should use sprintf to ensure that each cell is formatted to the same width. That works for the headers, the blank padding, one-digit dates, and two-digit dates.

def print_cal(starting_day_of_week, month_len)   days = %w(Mon Tue Wed Thu Fri Sat Sun)      leading_pad = [nil] * (starting_day_of_week - 1)   dates = (1..month_len).to_a    calendar = days + leading_pad + dates   calendar.each_slice(7) do |week|     puts week.map { |date| sprintf('%3s', date) }.join(' ')   end end 
 
 

Relacionados problema

4  Reemplazo de cadenas de espacios en blanco por pestañas y espacios en blanco para lograr el mismo espaciado  ( Replacing strings of blanks by tabs and blanks to achieve same spacing ) 
#include <stdio.h> #define MAXLINE 1000 /* Maximum length of a line */ #define TABSTOP 4 /* Length of tabstop */ int getLine(char line[], int limi...

3  Proveedor de formato extensible  ( Extendable format provider ) 
Necesitaba una Mejor Opciones de formato de cadena como public class JavaClass { ... public List<GenericEntry> getAllGenericEntries() { r...

5  Persiste los datos por serializando / deserializando objetos que se envían a ella  ( Persist data by serializing deserializing objects that are sent to it ) 
He creado la siguiente clase para persistir los datos por serializando / deserializando objetos que se envían a él. Me gustaría saber si hay una mejor manera ...

2  Formateo de un precio en SWIFT usando una extensión vs. una clase  ( Formatting a price in swift using an extension vs a class ) 
Tengo un precio como un Double , que debería formatearlo como un String . ¿Debo usar una extensión en lugar de clase clásica para encapsular "Formater", "...

3  Número Pirámide en Java  ( Number pyramid in java ) 
La función func(int m,int n) Salidas (para M = 3, N = 5): 3 34 345 34 3 Se me ocurrió este código: void func(int m,int n) { for(int i=1;i<n-...

4  Resaltador de sintaxis para HTML y PHP  ( Syntax highlighter for html and php ) 
He creado una aplicación JavaScript para resaltar la sintaxis de HTML y PHP. Sé que muchos resaltadores de sintaxis están disponibles hoy en día, acabo de cre...

1  Ejercicio: limpiar y formatear un número de teléfono en Clojure  ( Exercism clean and format a phone number in clojure ) 
Declaración de problemas Número de teléfono Escriba un programa que limpie los números de teléfono ingresados ​​por el usuario para que puedan ser envi...

8  Inventario de juegos de fantasía - CH. 5 Automatizar las cosas aburridas  ( Fantasy game inventory ch 5 automate the boring stuff ) 
Aquí hay un ejercicio de práctica: inventario de juegos de fantasía $ - $ estás creando un videojuego de fantasía. La estructura de datos para mode...

11  Imprimiendo un calendario por un mes basado en la entrada del usuario  ( Printing a calendar for a month based on user input ) 
Tengo un código de código largo que tiene muchos puntos de repetición. Estoy seguro de que no toma esta cantidad de código para crear un calendario simple, pe...

4  Manera más corta posible de imprimir una tabla específica  ( Shortest possible way of printing a specific board ) 
Estoy tratando de imprimir una tabla exactamente como esta con la matriz multidimensional. char score[10][10] = {' '}; a b c d e f g h i j +-...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos