Anonymous user
List comprehensions: Difference between revisions
→{{header|Ruby}}: Switch to using Enumerable#select.
m (→{{header|Scheme}}: Add link to SRFI-42) |
(→{{header|Ruby}}: Switch to using Enumerable#select.) |
||
Line 704:
=={{header|Ruby}}==
Enumerable#select comprises a list from one variable (like grep() in Perl).
* <tt>(1..100).select { |x| x % 3 == 0 }</tt> is the list of all x, from 1 to 100, such that x is a multiple of 3.
* <tt>methods.select { |name| name.length <= 5 }</tt> is the list of all names, from methods of <tt>self</tt>, such that each name is not longer than 5 characters.
Ruby's object-oriented style enforces writing 1..100 before x. Think not of x in 1..100. Think of 1..100 giving x.
There is no elegant way to comprise a list from multiple variables. Pythagorean triplets need three variables, with 1..n giving x, then x..n giving y, then y..n giving z. A less than elegant way is to nest three calls to Enumerable#map, to bundle these 3 variables into an array [x, y, z].
=== Ruby 1.9.2 ===
{{works with|Ruby|1.9.2 or later}}
<lang ruby>n = 20
# select Pythagorean triplets
r = ((1..n).flat_map { |x|
(x..n).flat_map { |y|
(y..n).map { |z| [x, y, z] }}} \
.select { |x, y, z| x * x + y * y == z * z })
p r # print the array _r_</lang>
Output: <tt>[[3, 4, 5], [5, 12, 13], [6, 8, 10], [8, 15, 17], [9, 12, 15], [12, 16, 20]]</tt>
Ruby 1.9.2 introduces a new method, Enumerable#flat_map.
* The inner <tt>(y..n).map { ... }</tt> returns an array of all triplets for all z given some x, y.
* The middle <tt>(x..n).flat_map { ... }</tt> concatenates the inner arrays for all y given some x.
* The outer <tt>(1..n).flat_map { ... }</tt> concatenates the middle arrays for all x.
* We never flatten the triplets; the inner <tt>map</tt> is not <tt>flat_map</tt>. So we produce an array of triplets like [[1, 1, 1], [1, 1, 2]], not a flat array like [1, 1, 1, 1, 1, 2].
* The final <tt>.select { ... }</tt> looks at each triplet in our array of triplets, and comprises the Pythagorean triplets.
=== Ruby 1.8.7 ===
{{works with|Ruby|1.8.7 or later}}
<lang ruby>n = 20
# select Pythagorean triplets
r = ((1..n).map { |x|
(x..n).map { |y|
(y..n).map { |z| [x, y, z] }}}.flatten(2) \
.select { |x, y, z| x * x + y * y == z * z })
p r # print the array _r_</lang>
Ruby before 1.9.2 is without Enumerable#flat_map, so we switch to using Enumerable#map. We get an array of arrays of arrays of triplets. We use <tt>.flatten(2)</tt> to convert this to an array of triplets.
* <tt>map</tt> and <tt>collect</tt> are the same method.
* <tt>.flatten(2)</tt> is a shorter alternative to <tt>.reduce(:+).reduce(:+)</tt>.
=== Ruby 1.8.6 ===
{{works with|Ruby|1.8.6}}
<lang ruby>n = 20
# select Pythagorean triplets
r = ((1..n).map { |x|
(x..n).map { |y|
(y..n).map { |z| [x, y, z] }}} \
.inject([]) { |a, b| a.concat b } \
.inject([]) { |a, b| a.concat b } \
.select { |x, y, z| x * x + y * y == z * z })
p r # print the array _r_</lang>
Anyone with Ruby 1.8.6 should probably upgrade to Ruby 1.8.7.
=={{header|Scala}}==
|