Печать значений в хэше с использованием условного оператора «for» и Ruby's .each - PullRequest
2 голосов
/ 30 апреля 2019

Я пытаюсь решить, что должно быть очень простой проблемой в Ruby.Моя цель - взять следующий хеш, распечатать значения и ключи, используя циклы for и метод .each.

my_stocks = { 'Apple' => { 'symbol' => 'AAPL', 'price' => 100 },
          'Google' => { 'symbol' => 'GOOG', 'price' => 1150 },
          'Tesla' => { 'symbol' => 'TSLA', 'price' => 295 },
          'Microsoft' => { 'symbol' => 'MSFT', 'price' => 95},
          'Netflix' => { 'symbol' => 'NFLX', 'price' => 300},
          'Facebook' => { 'symbol' => 'FB', 'price' => 175},
          'Amazon' => { 'symbol' => 'AMZN', 'price' => 1250} }

Итак, я использую этот определенный метод для печати всего хеша:

def execute_exercise(my_stocks)
for i, j in my_stocks
  puts j
end
end

Очевидно, это удается.Далее я пытаюсь использовать цикл for для печати только тех значений ключей, которые превышают 500.

Каждое решение, с которым я столкнулся, вызывает ошибку в Ruby:

rbtest.rb:18:in `>': no implicit conversion of Fixnum into Hash (TypeError)
from rbtest.rb:18:in `block in execute_exercise'
from rbtest.rb:18:in `each'
from rbtest.rb:18:in `execute_exercise'
from rbtest.rb:25:in `<main>'

Я предпринял следующие попытки:

my_stocks.each {|symbol,price| puts symbol if price > 500}
for q, e in my_stocks.to_i < 500
      puts e
    end

Я ожидаю, что значения будут напечатаны из хэша, но очевидно, что я что-то здесь упускаю.Я не могу преобразовать fixnum в хеш без .to_h, но это даже работает?Я просто неправильно понимаю петли или это что-то еще?

Ответы [ 2 ]

4 голосов
/ 30 апреля 2019

Вы просите Руби сделать слишком много сразу:

for q, e in my_stocks.to_i < 500

Это действительно не имеет никакого смысла.for перебирает контейнер.to_i возвращает целое число.x.to_i < n возвращает логическое значение.Вы не можете перебрать логическое значение.Плюс, my_stocks - это хеш, и он не делает to_i, так что вся эта строка - не то, что может понять Руби.

Вместо этого думайте о проблеме иначе.Рубиновый способ - разбить это на шаги.Во-первых, найдите все акции по определенному значению:

my_stocks.select do |_name, data|
  data['price'] > 500
end.each do |name, data|
  # ... print or whatever
end

Где это касается Enumerable , чтобы помочь решить проблему в два этапа.select для фильтрации, each для итерации.В Ruby for на самом деле не используется, это действительно никогда не лучший инструмент для работы.

Реальная сила Enumerable заключается в том, что вы можете связать одну операцию прямо в следующую.end.each может показаться странным для тех, кто не знаком с Ruby, но именно так Ruby легко справляется со сложными операциями.

Например, фильтрация и сортировка по цене (от высокой к низкой) - это всего лишь небольшая модификация:

my_stocks.select do |_name, data|
  data['price'] > 500
end.sort_by do |_name, data|
  -data['price']
end.each do |name, data|
  # ... print or whatever
end

Элемент -data['price'] - это простой способ избежать необходимости поменять значения позже.Обычно сортировка происходит по возрастанию, поэтому инвертирование сортируется по убыванию, так как самое высокое значение становится самым низким.

0 голосов
/ 30 апреля 2019

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

for q, e in my_stocks
  next unless e['price'] > 500 
  puts q
  puts e
end

Это выдаст:

Google
{"symbol"=>"GOOG", "price"=>1150}
Amazon
{"symbol"=>"AMZN", "price"=>1250}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...