People keep telling me I'm writing “C style iterators” in ruby, and that I'm supposed to do it this other way, without the i++ thing

心已入冬 提交于 2019-12-24 08:57:44

问题


The details here aren't important, it's just an example, all that matters is the i=0, i+=1 action

def sortAndIndex
  #sorting keys
  @disco = Hash[@disco.sort]

  #basic setup for both input types
  @years = @disco.keys
  @albums = @disco.values
  sum = @years.count

  #setup for "albums" input
  @allalbums = []
  i = 0
  sum.times do
  thatyear = @years[i] + ", " + @albums[i]
  @allalbums << thatyear
  i += 1
 end
end

Now this does work, as should any other "i++" type ("C-style") iterator in ruby or most other languages. However, I keep hearing that ruby has this better way to do this, where basically I'd be passing a second parameter variable other than, here, 'a'.

What modifications would I make to do this and are there multiple "shortcuts" which ruby has involving these sorts of i++ ary[i] iterator problems?


回答1:


Yes, you should do things the "Ruby way" and forget about indexing. Why? Because it is idiomatic and looks nicer. You pass in a block of code to be executed upon each element of a collection. How the elements are stored, in what order, if they can be indexed into, is all irrelevant.

# nice, eh?
some_array.each do |elem|
  some_action(elem)
end

If you need an index counter (you don't in your example) use each_with_index instead.

Also note that the concept of blocks is important in Ruby outside of iterating a collection. What you have there is... odd... and you should listen to them, but many methods take blocks as arguments (or optional arguments) which do not return collections which can be indexed. For example, File.open takes a block and, if supplied, closes the file for you when the block returns

Also, another thing to note; your naming conventions are atypical for Ruby. Rubyists use lowercase function and variable names with underscores_between_words. Best to stick with the community here.




回答2:


People are telling you about this:

ary.each do |a|
  puts a
end

Much simpler, isn't it?

Update

This is how I would write your updated example in idiomatic ruby

def sort_and_index
  @disco.sort.map do |year, album|
    "#{year}, #{album}"
  end
end

I'm not sure, if you needed all those instance variables for later use or not.




回答3:


The times method doesn't pass a second argument to the block. You may be looking for each_with_index, which passes the object and the index of that object to the block:

ary.each_with_index do |object, i|
  puts "Index #{i} => #{object.inspect}"
end

But ultimately yes, Ruby has several ways to iterate over a collection, and they're all better than C-style for loops :-)



来源:https://stackoverflow.com/questions/11403712/people-keep-telling-me-im-writing-c-style-iterators-in-ruby-and-that-im-sup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!