I'm pretty sure select used to use the actual value of the called block, instead of treating it as just a truthy/falsey boolean. I know this is unconventional, but it's a really nice, compact way of expressing map and filter in one shot, like list comprehension:
(1..10).select { |a| a * a if a > 5 }
Was it ever there, or did I just have a dream about it? It's easy to implement... just wondering.
I always thought it would be nice if Ruby had a method for this.
Facets' provides #compact_map. Perhaps not the sexiest name (once upon
a time it was called #collect_if), but it's describes the behavior
properly.
T.
···
On Nov 29, 10:39 pm, Mike Austin <"mike[nospam]"@mike-austin.com> wrote:
I'm pretty sure select used to use the actual value of the called block,
instead of treating it as just a truthy/falsey boolean. I know this is
unconventional, but it's a really nice, compact way of expressing map and
filter in one shot, like list comprehension:
(1..10).select { |a| a * a if a > 5 }
Was it ever there, or did I just have a dream about it? It's easy to
implement... just wondering.
The only time this doesn't work is when you want to preserve nils in
your original array.
-- Mark.
···
On Nov 29, 10:46 pm, Mike Austin <"mike[nospam]"@mike-austin.com> wrote:
I'm pretty sure select used to use the actual value of the called block,
instead of treating it as just a truthy/falsey boolean. I know this is
unconventional, but it's a really nice, compact way of expressing map and
filter in one shot, like list comprehension:
(1..10).select { |a| a * a if a > 5 }
Was it ever there, or did I just have a dream about it? It's easy to
implement... just wondering.
I'm pretty sure select used to use the actual value of the called block, instead of treating it as just a truthy/falsey boolean.
I am pretty sure it did never. Maybe you have a combination with to_enum in mind or rather inject?
I know this is unconventional, but it's a really nice, compact way of expressing map and filter in one shot, like list comprehension:
(1..10).select { |a| a * a if a > 5 }
Was it ever there, or did I just have a dream about it? It's easy to implement... just wondering.
Maybe 1.9 has a nifty trick, I don't use it that often yet.
(0..10).each_with_object() {|e,a| a << (e * e) if e > 5 }
Basically inject with a sticky accumulator.
David
--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS (Jan 12-15) | ADVANCING WITH RAILS (Jan 19-22) *
Both in Fort Lauderdale, FL * Co-taught with Patrick Ewing
See http://www.rubypal.com for details
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2\)
Oh, I remember why it is called #compact_map now, rather then some
more concise name. And I've been meaning to bring it up again. Why not
let #compact itself take a block to do this?
T.
···
On Nov 30, 6:45 am, Trans <transf...@gmail.com> wrote:
On Nov 29, 10:39 pm, Mike Austin <"mike[nospam]"@mike-austin.com> > wrote:
> I'm pretty sure select used to use the actual value of the called block,
> instead of treating it as just a truthy/falsey boolean. I know this is
> unconventional, but it's a really nice, compact way of expressing map and
> filter in one shot, like list comprehension:
> (1..10).select { |a| a * a if a > 5 }
> Was it ever there, or did I just have a dream about it? It's easy to
> implement... just wondering.
I always thought it would be nice if Ruby had a method for this.
Facets' provides #compact_map. Perhaps not the sexiest name (once upon
a time it was called #collect_if), but it's describes the behavior
properly.
From: Mike Austin [mailto:"mike[nospam]"@mike-austin.com]
..
# (1..10).select { |a| a * a if a > 5 }
the difficulty there is that there is no clear separation bw the selection logic and the mapping logic
# Was it ever there, or did I just have a dream about it?
# It's easy to implement... just wondering.
it's easy in 1.9..
p (0..10).select_with_map ->(x){x<5}, ->(x){x*x}
[0, 1, 4, 9, 16]
I don't see that method in 1.9. Which version are you using?
David
--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS (Jan 12-15), Fort Lauderdale, FL
See http://www.rubypal.com for details
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2\)
> I'm pretty sure select used to use the actual value of the called block,
> instead of treating it as just a truthy/falsey boolean. I know this is
> unconventional, but it's a really nice, compact way of expressing map and
> filter in one shot, like list comprehension:
> (1..10).select { |a| a * a if a > 5 }
> Was it ever there, or did I just have a dream about it? It's easy to
> implement... just wondering.
This is what I do:
(1..10).collect{ |a| a * a if a > 5 }.compact
The only time this doesn't work is when you want to preserve nils in
your original array.
And that's exactly what I suggested for #compact, to take a block but
faster b/c it's one pass.
T.
···
On Dec 4, 9:44 am, Mark Thomas <m...@thomaszone.com> wrote:
On Nov 29, 10:46 pm, Mike Austin <"mike[nospam]"@mike-austin.com> > wrote:
On Sun, Nov 30, 2008 at 8:54 AM, Robert Klemme > <shortcutter@googlemail.com> wrote:
On 30.11.2008 04:46, Mike Austin wrote:
I'm pretty sure select used to use the actual value of the called block,
instead of treating it as just a truthy/falsey boolean.
I am pretty sure it did never. Maybe you have a combination with to_enum in
mind or rather inject?
I know this is unconventional, but it's a really nice, compact way of
expressing map and filter in one shot, like list comprehension:
(1..10).select { |a| a * a if a > 5 }
Was it ever there, or did I just have a dream about it? It's easy to
implement... just wondering.
Maybe 1.9 has a nifty trick, I don't use it that often yet.
As said, inject is always a good candidate for this:
irb(main):005:0> (1..10).inject() {|r,a| r << (a*a) if a > 5; r}
As Robert was the first to suggest inject I am left with the less
attractive joices
a.map{ |a| a > 5 ? a*a: nil}.compact # does not work for any &blk of course
or
myselection = proc{ |a| a*a if a > 5}
a.select(&myselection).map(&myselection)
or
module Enumerable
def map_selection &blk
select( &blk ).map( &blk )
end
end
There's also:
res =
(1..10).each {|e| res << (e * e) if e > 5 }
res
No shame in a local variable now and then
David
--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS (Jan 12-15) | ADVANCING WITH RAILS (Jan 19-22) *
Both in Fort Lauderdale, FL * Co-taught with Patrick Ewing
See http://www.rubypal.com for details
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2\)
In message "Re: Enumerable#select used to return actual values" on Fri, 5 Dec 2008 00:47:45 +0900, Trans <transfire@gmail.com> writes:
(1..10).collect{ |a| a * a if a > 5 }.compact
The only time this doesn't work is when you want to preserve nils in
your original array.
And that's exactly what I suggested for #compact, to take a block but
faster b/c it's one pass.
I don't deny the existence of use case of such method (although I
cannot think of any realistic one right now), but its name should not
be #compact, since it does far more than compacting the receiver.
In message "Re: Enumerable#select used to return actual values" > on Sun, 30 Nov 2008 19:47:13 +0900, "David A. Black" <dblack@rubypal.com> writes:
--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS (Jan 12-15), Fort Lauderdale, FL
See http://www.rubypal.com for details
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2\)
Hmmm
just a little brainstorming on this
[1, nil, false].compact --> [1]
[1, nil, false].compact_by{ |x| x.nil?} --> [1, false]
o = Object::new
a.collect{ |x| some_condition(x) ? x : o}.compact_by{ |x| x==o}
But actually the implementation is *easy*
module Enumerable
alias_method :compact_by, :reject ###
end
However what about
module Enumerable
alias_method :__old_reject__, :reject
def reject( *args, &blk )
raise SomeDescriptiveError unless blk.nil? || args.empty?
return __old_reject__( &blk ) if blk
__old_reject__{ |x| args.include? x }
end
end
I guess I might put this into Labrador
Cheers
Robert
or
···
On Thu, Dec 4, 2008 at 5:07 PM, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
Hi,
In message "Re: Enumerable#select used to return actual values" > on Fri, 5 Dec 2008 00:47:45 +0900, Trans <transfire@gmail.com> writes:
>> (1..10).collect{ |a| a * a if a > 5 }.compact
>>
>> The only time this doesn't work is when you want to preserve nils in
>> your original array.
>
>And that's exactly what I suggested for #compact, to take a block but
>faster b/c it's one pass.
I don't deny the existence of use case of such method (although I
cannot think of any realistic one right now), but its name should not
be #compact, since it does far more than compacting the receiver.
matz.
--
Ne baisse jamais la tête, tu ne verrais plus les étoiles.
On Thu, Dec 4, 2008 at 10:07 AM, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
I don't deny the existence of use case of such method (although
I cannot think of any realistic one right now), but its name
should not be #compact, since it does far more than compacting
the receiver.