开发者

Re-writing a "better" code

I am using Ruby 1.9 and I would like to know if there is a "better" way to write the followi开发者_StackOverflowng code.

  array_one = []
  array_two = []
  some_array.each { |value|
    array_one << value.id
    array_two << value.name
  }

I "don't like" to initialize array_one and array_two like in the above example and then add in those value.id and value.name. This because and mostly for a better understanding and reading of the code in my application.

I would like to provide the same functionality but with a "better" coding. Is it possible?


The code pattern you have there, is usually a sure sign of a fold (or more generally a catamorphism) wanting to get out. Ruby does provide a built-in method for folding, for historical reasons it is called inject.

Untested:

array_one, array_two = some_array.
  inject([[], []]) {|(array_one, array_two), value|
    [array_one << value.id, array_two << value.name]
}

Not sure whether you think this is "better" or not. For someone who understands what a fold is, this is probably clearer. For someone who doesn't, it's probably not.

(Although I think that if you don't understand what a fold is, then you are not a very good Ruby programmer, or even a very good programmer at all, but that is just my opinion.)

However, saying that some iteration is a fold isn't really terribly useful, since fold is a general method of iteration (which means that every form of iteration can be expressed as a fold). What you really have here, is a map:

array_one, array_two = some_array.map(&:id), some_array.map(&:value)

Note that this will traverse some_array twice. However, unless you have credible benchmarks and profiling results that show that this double traversal is a major source of performance troubles in your application, you really shouldn't worry about that.


You could use the Array#collect method:

array_one = some_array.collect { |value| value.id }
array_two = some_array.collect { |value| value.name }

As Jörg W Mittag mentioned in his answer, this solution will also traverse the source array twice.


You may want to use transpose to transform an n-element array containing two-element arrays into two n-element arrays:

array_one, array_two = some_array.map {|value| [value.id, value.name]}.transpose

Here's the RDoc link, though it's fairly terse.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜