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.
精彩评论