Advanced conditionals

A

Alain m. Lafon

Hi there,

is there a way to include conditionals in something like:

g.labels = Hash[*invoice.collect {|v| [v["Scandate"].to_s,
"1"]}.flatten]

In this example I don't want to include entries to the hash where
v["Scandate"] is an empty string.

Help is as always very much appreciated - thanks in advance,
Alain M. Lafon
 
A

Alain m. Lafon

I forgot to mention that I do realize that there is an delete_if option
for Hashes. Probably I should have searched for a better example, but
what I want to know is wheter I can implement small functions in any
statement(like lambdas in Lisp).
 
P

Peña, Botp

RnJvbTogQWxhaW4gbS4gTGFmb24gW21haWx0bzpwcmVlay5hbWxAZ21haWwuY29tXSANCiMgaXMg
dGhlcmUgYSB3YXkgdG8gaW5jbHVkZSBjb25kaXRpb25hbHMgaW4gc29tZXRoaW5nIGxpa2U6DQoj
ICAgIGcubGFiZWxzID0gSGFzaFsqaW52b2ljZS5jb2xsZWN0IHt8dnwgW3ZbIlNjYW5kYXRlIl0u
dG9fcywNCiMgIjEiXX0uZmxhdHRlbl0NCiMgSW4gdGhpcyBleGFtcGxlIEkgZG9uJ3Qgd2FudCB0
byBpbmNsdWRlIGVudHJpZXMgdG8gdGhlIGhhc2ggd2hlcmUNCiMgdlsiU2NhbmRhdGUiXSBpcyBh
biBlbXB0eSBzdHJpbmcuDQoNCnlvdSdsbCBoYXZlIHRvIG1ha2UgdHdvIHBhc3NlcyAod2lzaCB0
aGVyZSB3YXMgYSByZWplY3Qvc2VsZWN0K21hcCBjb21iaSkNCg0Kc2FtcGxlLCAobm90ZSB1bnRl
c3RlZCwgaSBqdXN0IHR5cGUgaXQgaW4gdGhpcyBlbWFpbCA6KQ0KDQogIGcubGFiZWxzID0gSGFz
aFsqaW52b2ljZS5yZWplY3R7fHZ8IFt2WyJTY2FuZGF0ZSJdLiB0b19zLnN0cmlwLiBlbXB0eT99
LiBjb2xsZWN0e3x2fCBbdlsiU2NhbmRhdGUiXS50b19zLCAiMSJdfS5mbGF0dGVuXQ0KDQoNCg==
 
P

Pedro Silva

H,
g.labels = Hash[*invoice.collect {|v| [v["Scandate"].to_s,
"1"]}.flatten]

In this example I don't want to include entries to the hash where
v["Scandate"] is an empty string.

The method collect/map has "friends". What you're looking for is select
or reject. Select returns the elements from the container where the
condition specified in the block evaluates to true, reject does the
opposite - returns the elements that evaluate to false.

Consider the following example:

invoice = {:a => "a", :b => "b", :c => "", :d => "c", :e => ""}
invoice.select { |a, b| b != "" } # [[:a, "a"], [:b, "b"], [:d, "c"]]

Pedro Silva.
 
P

Peña, Botp

IyBzYW1wbGUsIChub3RlIHVudGVzdGVkLCBpIGp1c3QgdHlwZSBpdCBpbiB0aGlzIGVtYWlsIDop
DQojIA0KIyAgIGcubGFiZWxzID0gSGFzaFsqaW52b2ljZS5yZWplY3R7fHZ8IFt2WyJTY2FuZGF0
ZSJdLiANCg0KICAgICAgICAgICAgLi4uLi4gaSB0aGluayAgdGhpcyBicmFja2V0IF4gc2hvdWxk
IGJlIHJlbW92ZWQsIHNvcnJ5DQoNCiMgdG9fcy5zdHJpcC4gZW1wdHk/fS4gY29sbGVjdHt8dnwg
W3ZbIlNjYW5kYXRlIl0udG9fcywgIjEiXX0uZmxhdHRlbl0NCiMgDQojIA0KIyANCg==
 
R

Robert Dober

Hi there,

is there a way to include conditionals in something like:

g.labels =3D Hash[*invoice.collect {|v| [v["Scandate"].to_s,
"1"]}.flatten]

In this example I don't want to include entries to the hash where
v["Scandate"] is an empty string.

Help is as always very much appreciated - thanks in advance,
Alain M. Lafon

I sometimes decide against the map.select (or better select.map )
chaining using compact

ary.map{ |x| c(x) && f(x) }.compact

HTH
Robert

--=20
C'est v=E9ritablement utile puisque c'est joli.

Antoine de Saint Exup=E9ry
 
P

Peña, Botp

From: David A. Black [mailto:[email protected]]=20
..
#For a little while, 1.9 allowed you to do this:
#>> e =3D [1,2,3].enum_for:)map, &lambda {|x| x * 10 })
#=3D> #<Enumerable::Enumerator:0x39038c>
#>> e.select {|n| n > 10 }
#=3D> [20, 30]
#But #enum_for no longer accepts a &block-style argument. The same code
#in current 1.9 would give you [], because it would ignore the lambda
#and just do a pass-through mapping.
#I'm still unclear as to why this behavior was removed. It seems to me
#that its removal reduces the usefulness of enumerators drastically.

maybe because it does not look any better than the simpler (but less =
efficient)
e =3D [1,2,3].select{|n| n>1}.map{|x| x*10}
=3D>[20,30]

i was actually dreaming of ruby supporting multiple blocks
so that you can do simply
e =3D [1,2,3].select{|n| n>1},{|x| x*10}
=3D>[20,30]

meaning, do a (re)map if a second code block is passed

kind regards -botp
 
B

Bill Kelly

From: "David A. Black said:
[...] but you cannot, any longer, do this:

irb(main):007:0> a = [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):008:0> e = a.enum_for:)map, &lambda {|x| x * 10 })
=> #<Enumerable::Enumerator:0x3d7444>
irb(main):009:0> e.next
=> 10

You'll get 1 now, rather than 10. I'm still very puzzled by the
removal of this capability.

Maybe worth asking on ruby-core? Still 13 days till the
feature freeze...!



Regards,

Bill
 
D

David A. Black

Hi --

From: "David A. Black said:
[...] but you cannot, any longer, do this:

irb(main):007:0> a = [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):008:0> e = a.enum_for:)map, &lambda {|x| x * 10 })
=> #<Enumerable::Enumerator:0x3d7444>
irb(main):009:0> e.next
=> 10

You'll get 1 now, rather than 10. I'm still very puzzled by the
removal of this capability.

Maybe worth asking on ruby-core? Still 13 days till the
feature freeze...!

I did. Shugo did discuss it some, but I'm afraid I still didn't
understand, or maybe I just wasn't convinced. I think it probably
boils down to efficiency, though it seems to me to be an example of
something so powerful and potentially useful that efficiency wouldn't
(up to a point) be a deal-breaker.


David

--
Rails training from David A. Black and Ruby Power and Light:
Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
Advancing with Rails January 19-22 Fort Lauderdale, FL *
* Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!
 
P

Peña, Botp

From: David A. Black [mailto:[email protected]]=20
...
e =3D [1,2,3].select{|n| n>1},{|x| x*10}
=3D>[20,30]

meaning, do a (re)map if a second code block is passed
That comes up periodically.... It never appealed to me; I guess I
think of it like a method having two argument lists. Besides, how

indeed. and i think we agree to disagree there.
i prefer that code blocks be generics and be passed like normal =
arguments. ergo, they will now be explicitly defined in def. less =
invisible ink? ;)
would you distinguish it from a hash literal? :)

strengthen the parser. currently, since a code block come last, then the =
rest should be code blocks, if any. also, if a token arg sequence of =
"{|" is caught, then that should start a code block. meaning {||} is =
always a code block.

kind regards -botp
 
P

Peña, Botp

From: David A. Black [mailto:[email protected]]=20
..
So all you gain, really, is not having to write "proc". I don't think
it's worth it; I like the whole block/yield/iterator thing too much.

i like yield, too. so much, that i want another yield.
how about yield_next to yield to the next block? we allow max of two =
blocks only..
That's ugly, though -- you'd end up with a lot of empty ||'s.

it's not too ugly if it's not empty since we usually end up passing proc =
args anyway. in 1.9 we have ->{}, and as compared to {||}, we get same =
number of characters yet i still prefer the latter considering that i'm =
used to it and it's still is clearer/cleaner.

but anyway, this feature is no big deal to me. i'm even happy passing =
array of procs or just looping w each instead of select+map. it's just =
that sometimes i wish there was some way i code just type in easily like =
select+map combination in one simple streamlined fast code..

thank you for the discussion.
kind regards -botp
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top