Самый простой способ заполнить массив пользовательским вводом / с наименьшим количеством строк кода - PullRequest
1 голос
/ 21 октября 2019

Какой самый простой способ создания массива из x элементов, состоящих из смешанных типов данных (т. Е. Массива со строками, целыми числами и числами с плавающей запятой) из пользовательского ввода

Пока что я сделал некоторый код, которыйработал с использованием цикла for, но я хотел знать, есть ли способ оптимизировать его и иметь наименьшее количество строк кода.

puts "how many elements?"

max = gets.to_i
array = []

for i in 0..max - 1
  puts "are you entering in a string, an int or a float?"
  data_type = gets.chomp

  if %W[string STRING String s S].include?(data_type)
    puts "enter in a string"
    array[i] = gets.chomp
  elsif %W[int INT Int i I].include?(data_type)
    puts "enter an int"
    array[i] = gets.to_i
  elsif %W[Float FLOAT float f F].include?(data_type)
    puts "enter a float"
    array[i] = gets.to_f
  end
end

print array

Ответы [ 5 ]

5 голосов
/ 21 октября 2019

Минимальное количество строк? Один. Если у вас есть max:

array = max.times.map { gets.chomp.then { |l| case l when /^\d+$/ then l.to_i when /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/ then l.to_f else l end } }

Это еще короче (хотя некоторые люди будут возражать):

array = max.times.map { gets.chomp.then { |l| Integer(l) rescue Float(l) rescue l } }

Хотя было бы более читабельным написать его в несколько строк.

Обратите также внимание, что рубисты в основном делают вид, что for не существует в языке и обычно заменяют его на Enumerable#each, Integer#times и т. П.


Это несовсем как то, что у тебя есть;Мой код делает невозможным иметь строку, которая будет действительным числом, например, "2.0". Ваш код не так уж плох, если вы хотите эту функциональность (и одержимость количеством строк, как правило, ошибочна). Вещи, которые я бы изменил:

  • Петля. array = max.times.map do ... end более for в любое время. (Это также делает явное присвоение array[i] ненужным.)

  • "float".start_with?(data_type.downcase) вместо %W[Float FLOAT float f F].include?(data_type), поэтому вам не нужно беспокоиться о перечислении всех вариантов.

2 голосов
/ 21 октября 2019

ОК, я укушу.

p Array.new(puts("How many elements?") || gets.to_i) {
  puts("Are you entering in a string, an int or a float?") ||
  case(gets.chomp)
  when "string", "S" then (puts("Enter a string")   || gets.chomp)
  when "int", "INT"  then (puts("Enter an integer") || gets.to_i)
  when "float", "F"  then (puts("Enter a float")    || gets.to_f)
  end
}

Следующий диалог:

How many elements?: 3

Are you entering in a string, an int or a float?: int
Enter an integer: 5

Are you entering in a string, an int or a float?: S    
Enter a string: hi

Are you entering in a string, an int or a float?: F
Enter a float: 3.4

приведет к отображению (и возврату) следующего:

[5, "hi", 3.4]

Я использовал p вместо puts (который отображал бы элементы этого массива по одному на строку), чтобы прояснить, что это массив, который отображается. Обратите внимание, что каждый puts во фрагменте возвращает nil, поэтому nil || x #=> x.

Этот фрагмент имеет восемь строк, но его можно уменьшить до одной, удалив символы новой строки:

p Array.new(puts("How many elements?") || gets.to_i) { puts("Are you entering in a string, an int or a float?") || case(gets.chomp) when "string", "S" then  (puts("Enter a string") || gets.chomp) when "int", "INT"  then (puts("Enter an integer") || gets.to_i) when "float", "F" then (puts("Enter a float") || gets.to_f) end }
2 голосов
/ 21 октября 2019

Без изменения какого-либо поведения, кроме принятия string, int и float как нечувствительного к регистру (например, stRinG теперь также работает), вы можете сделать что-то вроде этого.

puts "how many elements?"
max = gets.to_i

array = max.times.map do
  puts "are you entering in a string, an int or a float?"

  case gets
  when /\A(string|s)\Z/i
    puts "enter in a string"
    gets.chomp
  when /\A(int|i)\Z/i
    puts "enter an int"
    gets.to_i
  when /\A(float|f)\Z/i
    puts "enter a float"
    gets.to_f
  end
end

print array

Примечание: Возможно, вы захотите добавить else в case -statement для обработки сценария, который пользователь не вводит string, int или float. В настоящее время это приведет к значению nil в массиве.

Возможно, вы захотите реализовать это следующим образом:

case gets
when # ...
  #...
else
  redo
end
0 голосов
/ 22 октября 2019

До сих пор я создал некоторый код, который работал с использованием цикла for, но я хотел знать, есть ли способ оптимизировать его и иметь наименьшее количество строк кода.

В Ruby новые строки никогда не требуются, поэтому «наименьшее количество строк кода» для любой проблемы в Ruby равно всегда 1:

puts "how many elements?"; max = gets.to_i; array = []; for i in 0..max - 1 do puts "are you entering in a string, an int or a float?"; data_type = gets.chomp; if %W[string STRING String s S].include?(data_type) then puts "enter in a string"; array[i] = gets.chomp elsif %W[int INT Int i I].include?(data_type) then puts "enter an int"; array[i] = gets.to_i elsif %W[Float FLOAT float f F].include?(data_type) then puts "enter a float"; array[i] = gets.to_f end end; print array
0 голосов
/ 21 октября 2019

Использование Hash в качестве помощника:

datatypes = { i: { convert: 'to_i', text: 'an integer' }, f: { convert: 'to_f', text: 'a float' } }
datatypes.default = { convert: 'to_s', text: 'a string' }

array = max.times.map do
  puts "Are you entering in an (i)nt, a (f)loat or a string (default)?"
  data_type = gets[0].downcase.to_sym # you can improve this part
  puts "enter in #{datatypes[data_type][:text]}"
  gets.chomp.send(datatypes[data_type][:convert])
end

p array
p array.map &:class
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...