RUBY DRY to replace 6 lines in 1

J

Josselin

I have a group of lines (used in Googlemaps display) based on 2 arrays :

zl = 9 if farthest_proposition.distance_to(origin) < = 25.0
zl = 10 if farthest_proposition.distance_to(origin) <= 15.0
zl = 11 if farthest_proposition.distance_to(origin) <= 10.0
zl = 12 if farthest_proposition.distance_to(origin) <= 5.0
zl = 13 if farthest_proposition.distance_to(origin) < =2.0
zl = 14 if farthest_proposition.distance_to(origin) <= 1.0

how could I replace it the dryest way possible ?

zl = [9, 10, 11, 12, 13, 14]
distance = [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]
farthest_proposition.distance_to(origin) is never > 25 (eliminated before..)
farthest_proposition.distance_to(origin) can be 0.0, never negative

thanks for yoru suggestions...

joss
 
S

Sebastian Probst Eide

Couldn't you write something like this?

def get_zl(origin)
temp_val = farthest_proposition.distance_to(origin)
[{:value=>1.0, :zl=>14}, {:value=>2.0, :zl=>13},
{:value=>5.0, :zl=>12}, {:value=>10.0, :zl=>11},
{:value=>15.0, :zl=>10}, {:value=>25.0, :zl=>9}].each {|pair| return
pair[:zl] if temp_val <= pair[:value]}
end

Maybe it is not the smartest way to solve the problem, but it is a
different solution none the less. Hope it helps and let's you find
the ultimate solution yourself!
I didn't replace it with one line as you requested, but with four...


Best regards
Sebastian
 
J

Josselin

Couldn't you write something like this?

def get_zl(origin)
temp_val = farthest_proposition.distance_to(origin)
[{:value=>1.0, :zl=>14}, {:value=>2.0, :zl=>13}, {:value=>5.0,
:zl=>12}, {:value=>10.0, :zl=>11}, {:value=>15.0, :zl=>10},
{:value=>25.0, :zl=>9}].each {|pair| return pair[:zl] if temp_val <=
pair[:value]}
end

Maybe it is not the smartest way to solve the problem, but it is a
different solution none the less. Hope it helps and let's you find the
ultimate solution yourself!
I didn't replace it with one line as you requested, but with four...


Best regards
Sebastian

I have a group of lines (used in Googlemaps display) based on 2 arrays :

zl = 9 if farthest_proposition.distance_to(origin) < = 25.0
zl = 10 if farthest_proposition.distance_to(origin) <= 15.0
zl = 11 if farthest_proposition.distance_to(origin) <= 10.0
zl = 12 if farthest_proposition.distance_to(origin) <= 5.0
zl = 13 if farthest_proposition.distance_to(origin) < =2.0
zl = 14 if farthest_proposition.distance_to(origin) <= 1.0

how could I replace it the dryest way possible ?

zl = [9, 10, 11, 12, 13, 14]
distance = [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]
farthest_proposition.distance_to(origin) is never > 25 (eliminated before..)
farthest_proposition.distance_to(origin) can be 0.0, never negative

thanks for yoru suggestions...

joss

thanks a lot.. when trying to get DRY, I just wonder if it helps in
performance ..
in both cases we perform 6 IF..
 
K

Konrad Meyer

--nextPart1735617.YmkLPv5XtJ
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Quoth Josselin:
I have a group of lines (used in Googlemaps display) based on 2 arrays :
=20
zl =3D 9 if farthest_proposition.distance_to(origin) < =3D 25.0
zl =3D 10 if farthest_proposition.distance_to(origin) <=3D 15.0
zl =3D 11 if farthest_proposition.distance_to(origin) <=3D 10.0
zl =3D 12 if farthest_proposition.distance_to(origin) <=3D 5.0
zl =3D 13 if farthest_proposition.distance_to(origin) < =3D2.0
zl =3D 14 if farthest_proposition.distance_to(origin) <=3D 1.0
=20
how could I replace it the dryest way possible ?
=20
zl =3D [9, 10, 11, 12, 13, 14]
distance =3D [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]
farthest_proposition.distance_to(origin) is never > 25 (eliminated before= =2E.)
farthest_proposition.distance_to(origin) can be 0.0, never negative
=20
thanks for yoru suggestions...
=20
joss

zl =3D case farthest_proposition.distance_to(origin)
when 0..1
14
when 1..2
13
when 2..5
12
when 5..10
11
when 10..15
10
when 15..25
9
end

HTH,
=2D-=20
Konrad Meyer <[email protected]> http://konrad.sobertillnoon.com/

--nextPart1735617.YmkLPv5XtJ
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHJ3egCHB0oCiR2cwRAtyEAKC/EPouK4xAEXIOlVIhmZLoGsyehACgu2gI
KvJhHwI/b6XDrR+iCCxh2YE=
=Ihh1
-----END PGP SIGNATURE-----

--nextPart1735617.YmkLPv5XtJ--
 
M

Martin DeMello

I have a group of lines (used in Googlemaps display) based on 2 arrays :

zl = 9 if farthest_proposition.distance_to(origin) < = 25.0
zl = 10 if farthest_proposition.distance_to(origin) <= 15.0
zl = 11 if farthest_proposition.distance_to(origin) <= 10.0
zl = 12 if farthest_proposition.distance_to(origin) <= 5.0
zl = 13 if farthest_proposition.distance_to(origin) < =2.0
zl = 14 if farthest_proposition.distance_to(origin) <= 1.0

how could I replace it the dryest way possible ?

zl = [9, 10, 11, 12, 13, 14]
distance = [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]

s = farthest_proposition.distance_to(origin)
zl = distance.zip(zl.reverse) {|d, z| break [z,d] if s <= d}

martin
 
M

Martin DeMello

I have a group of lines (used in Googlemaps display) based on 2 arrays :

zl = 9 if farthest_proposition.distance_to(origin) < = 25.0
zl = 10 if farthest_proposition.distance_to(origin) <= 15.0
zl = 11 if farthest_proposition.distance_to(origin) <= 10.0
zl = 12 if farthest_proposition.distance_to(origin) <= 5.0
zl = 13 if farthest_proposition.distance_to(origin) < =2.0
zl = 14 if farthest_proposition.distance_to(origin) <= 1.0

how could I replace it the dryest way possible ?

zl = [9, 10, 11, 12, 13, 14]
distance = [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]

s = farthest_proposition.distance_to(origin)
zl = distance.zip(zl.reverse) {|d, z| break [z,d] if s <= d}

oops, that should be break z, of course, not break [z,d]

The basic idea is this: the block form of as.zip(bs) {|a, b|} iterates
over as and bs in parallel, and break argument both exits the current
iterator and returns its argument as the return value of the iterator.

martin
 
M

MenTaLguY

I have a group of lines (used in Googlemaps display) based on 2 arrays :

zl = 9 if farthest_proposition.distance_to(origin) < = 25.0
zl = 10 if farthest_proposition.distance_to(origin) <= 15.0
zl = 11 if farthest_proposition.distance_to(origin) <= 10.0
zl = 12 if farthest_proposition.distance_to(origin) <= 5.0
zl = 13 if farthest_proposition.distance_to(origin) < =2.0
zl = 14 if farthest_proposition.distance_to(origin) <= 1.0

how could I replace it the dryest way possible ?

zl = [9, 10, 11, 12, 13, 14]
distance = [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]
farthest_proposition.distance_to(origin) is never > 25 (eliminated
before..)
farthest_proposition.distance_to(origin) can be 0.0, never negative

FWIW, one line isn't necessarily a realistic goal; DRY doesn't always
mean a large savings in LOC, just maintainability (which an excessively
"golfed" solution can hurt) and often performance.

Assuming two arrays given above are called ZL and DISTANCE (they should
really be constants), one solution is:

farthest_distance = farthest_proposition.distance_to(origin)
zl = DISTANCE.zip(ZL.reverse).find { |distance, _|
farthest_distance <= distance
}.first

Note that eliminating the repeated calls to #distance_to will yield
a performance increase. You could also gain additional performance
by combining ZL and DISTANCE into an associative list:

# (distance, z1) sorted by distance
ZL_BY_DISTANCE = [
[ 1.0, 14 ],
[ 2.0, 13 ],
[ 5.0, 12 ],
[ 10.0, 11 ],
[ 15.0, 10 ],
[ 25.0, 9 ]
]

...at which point you could simply write:

farthest_distance = farthest_proposition.distance_to(origin)
zl = ZL_BY_DISTANCE.find { |distance, _|
farthest_distance <= distance
}.first

(Side note: you might want to consider avoiding lower-case l in
variable names if you can; it is hard to tell apart from the number 1
in many fonts.)

-mental
 
M

MenTaLguY

thanks a lot.. when trying to get DRY, I just wonder if it helps in
performance ..
in both cases we perform 6 IF..

I'd be more concerned with the multiple calls to #distance_to in the
original.

If there could be a lot of zoom levels (~50 or more), then it might
be worthwhile to replace the linear search with a binary search (giving
you only log2(N) tests to do rather than the full N), but with the small
number of zoom levels available in Google Maps, the extra complexity
likely isn't worth it.

I also wouldn't worry too much about performance unless this particular
piece of code is a measurable hot spot in your performance profile.
Otherwise, it's easy to tie yourself into knots worrying about the
performance of things which cannot have a significant impact on execution
time.

In the beginning, just focus on clarity and maintainability (which is what
DRY really speaks to): you'll often get a little performance improvement
and shorter code as side benefits without having to worry about either
directly.

-mental
 
M

MenTaLguY

(Side note: you might want to consider avoiding lower-case l in
variable names if you can; it is hard to tell apart from the number 1
in many fonts.)

(The exception being when it is clearly part of a word, like zoom_level.)

-mental
 
K

Konrad Meyer

--nextPart1391113.to4lkFZHQv
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Quoth MenTaLguY:
I have a group of lines (used in Googlemaps display) based on 2 array= s :
=20
zl =3D 9 if farthest_proposition.distance_to(origin) < =3D 25.0
zl =3D 10 if farthest_proposition.distance_to(origin) <=3D 15.0
zl =3D 11 if farthest_proposition.distance_to(origin) <=3D 10.0
zl =3D 12 if farthest_proposition.distance_to(origin) <=3D 5.0
zl =3D 13 if farthest_proposition.distance_to(origin) < =3D2.0
zl =3D 14 if farthest_proposition.distance_to(origin) <=3D 1.0
=20
how could I replace it the dryest way possible ?
=20
zl =3D [9, 10, 11, 12, 13, 14]
distance =3D [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]
farthest_proposition.distance_to(origin) is never > 25 (eliminated
before..)
farthest_proposition.distance_to(origin) can be 0.0, never negative
=20
FWIW, one line isn't necessarily a realistic goal; DRY doesn't always
mean a large savings in LOC, just maintainability (which an excessively
"golfed" solution can hurt) and often performance.
=20
Assuming two arrays given above are called ZL and DISTANCE (they should
really be constants), one solution is:
=20
farthest_distance =3D farthest_proposition.distance_to(origin)
zl =3D DISTANCE.zip(ZL.reverse).find { |distance, _|
farthest_distance <=3D distance
}.first
=20
Note that eliminating the repeated calls to #distance_to will yield
a performance increase. You could also gain additional performance
by combining ZL and DISTANCE into an associative list:
=20
# (distance, z1) sorted by distance
ZL_BY_DISTANCE =3D [
[ 1.0, 14 ],
[ 2.0, 13 ],
[ 5.0, 12 ],
[ 10.0, 11 ],
[ 15.0, 10 ],
[ 25.0, 9 ]
]
=20
...at which point you could simply write:
=20
farthest_distance =3D farthest_proposition.distance_to(origin)
zl =3D ZL_BY_DISTANCE.find { |distance, _|
farthest_distance <=3D distance
}.first
=20
(Side note: you might want to consider avoiding lower-case l in
variable names if you can; it is hard to tell apart from the number 1
in many fonts.)
=20
-mental

Anyone doing any sort of programming should be using a font that distinguis=
hes=20
1 and l.

Sorry if that sounds a bit harsh, but using a good font is important.

Regards,
=2D-=20
Konrad Meyer <[email protected]> http://konrad.sobertillnoon.com/

--nextPart1391113.to4lkFZHQv
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHJ4E1CHB0oCiR2cwRAtHXAJ46Vb3ofOVKCoFq7SsECYOVWEGh+gCgyLGV
Wy2lmkj9rZuJhnmJWjrfE3o=
=+ePt
-----END PGP SIGNATURE-----

--nextPart1391113.to4lkFZHQv--
 
M

MenTaLguY

Anyone doing any sort of programming should be using a font that
distinguishes 1 and l.

Sorry if that sounds a bit harsh, but using a good font is important.

This is very true, but there are plenty of situations where you can't
control the font your code will be viewed in. For example, in the case
of email and the web, you are often at the mercy of the font choices made
by your readers (and/or the makers of their software).

So, I'd suggest doing both: use good fonts when you can, and minimize
the use of ambiguous letters for the sake of those viewing your code under
less-than-ideal conditions.

-mental
 
J

Josselin

I have a group of lines (used in Googlemaps display) based on 2 arrays :

zl = 9 if farthest_proposition.distance_to(origin) < = 25.0
zl = 10 if farthest_proposition.distance_to(origin) <= 15.0
zl = 11 if farthest_proposition.distance_to(origin) <= 10.0
zl = 12 if farthest_proposition.distance_to(origin) <= 5.0
zl = 13 if farthest_proposition.distance_to(origin) < =2.0
zl = 14 if farthest_proposition.distance_to(origin) <= 1.0

how could I replace it the dryest way possible ?

zl = [9, 10, 11, 12, 13, 14]
distance = [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]
farthest_proposition.distance_to(origin) is never > 25 (eliminated
before..)
farthest_proposition.distance_to(origin) can be 0.0, never negative

FWIW, one line isn't necessarily a realistic goal; DRY doesn't always
mean a large savings in LOC, just maintainability (which an excessively
"golfed" solution can hurt) and often performance.

Assuming two arrays given above are called ZL and DISTANCE (they should
really be constants), one solution is:

farthest_distance = farthest_proposition.distance_to(origin)
zl = DISTANCE.zip(ZL.reverse).find { |distance, _|
farthest_distance <= distance
}.first

Note that eliminating the repeated calls to #distance_to will yield
a performance increase. You could also gain additional performance
by combining ZL and DISTANCE into an associative list:

# (distance, z1) sorted by distance
ZL_BY_DISTANCE = [
[ 1.0, 14 ],
[ 2.0, 13 ],
[ 5.0, 12 ],
[ 10.0, 11 ],
[ 15.0, 10 ],
[ 25.0, 9 ]
]

..at which point you could simply write:

farthest_distance = farthest_proposition.distance_to(origin)
zl = ZL_BY_DISTANCE.find { |distance, _|
farthest_distance <= distance
}.first

(Side note: you might want to consider avoiding lower-case l in
variable names if you can; it is hard to tell apart from the number 1
in many fonts.)

-mental

thanks a lot... I wrote that in my Ruby Notebook ! I'll keep it in
mind when coding.. I learned Ruby (because of Rails...) on my personal
desk, I need to progress
what are the best books beside the basic ones I have... to improve
Ruby coding ?

joss
 
M

MenTaLguY

farthest_distance = farthest_proposition.distance_to(origin)
Ah, I just noticed a bug here in my code. This should be
last, rather than .first, since the zoom level is the second
item in the pair.

-mental
 
K

Konrad Meyer

--nextPart1362676.ATX8umjz3b
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Quoth MenTaLguY:
=20
This is very true, but there are plenty of situations where you can't
control the font your code will be viewed in. For example, in the case
of email and the web, you are often at the mercy of the font choices made
by your readers (and/or the makers of their software).
=20
So, I'd suggest doing both: use good fonts when you can, and minimize
the use of ambiguous letters for the sake of those viewing your code under
less-than-ideal conditions.
=20
-mental

The same goes for your email client. GUI clients will let you change the fo=
nt=20
to something nice. Console clients, you can change your console emulator's=
=20
font (unless you're at a real console, in which case you're SOL :D).

Regards,
=2D-=20
Konrad Meyer <[email protected]> http://konrad.sobertillnoon.com/

--nextPart1362676.ATX8umjz3b
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHJ8rWCHB0oCiR2cwRArt8AKDPSDCXPB2a+tXJgWtViSJnwnPjegCeP1Gq
Oe6p57bwW5zhmUs2WIVHcJc=
=2rxj
-----END PGP SIGNATURE-----

--nextPart1362676.ATX8umjz3b--
 
J

Josselin

--nextPart1735617.YmkLPv5XtJ
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Quoth Josselin:
I have a group of lines (used in Googlemaps display) based on 2 arrays :
=20
zl =3D 9 if farthest_proposition.distance_to(origin) < =3D 25.0
zl =3D 10 if farthest_proposition.distance_to(origin) <=3D 15.0
zl =3D 11 if farthest_proposition.distance_to(origin) <=3D 10.0
zl =3D 12 if farthest_proposition.distance_to(origin) <=3D 5.0
zl =3D 13 if farthest_proposition.distance_to(origin) < =3D2.0
zl =3D 14 if farthest_proposition.distance_to(origin) <=3D 1.0
=20
how could I replace it the dryest way possible ?
=20
zl =3D [9, 10, 11, 12, 13, 14]
distance =3D [1.0, 2.0, 5.0, 10.0, 15.0, 25.0]
farthest_proposition.distance_to(origin) is never > 25 (eliminated before= =2E.)
farthest_proposition.distance_to(origin) can be 0.0, never negative
=20
thanks for yoru suggestions...
=20
joss

zl =3D case farthest_proposition.distance_to(origin)
when 0..1
14
when 1..2
13
when 2..5
12
when 5..10
11
when 10..15
10
when 15..25
9
end

HTH,
=2D-=20
Konrad Meyer <[email protected]> http://konrad.sobertillnoon.com/

--nextPart1735617.YmkLPv5XtJ
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHJ3egCHB0oCiR2cwRAtyEAKC/EPouK4xAEXIOlVIhmZLoGsyehACgu2gI
KvJhHwI/b6XDrR+iCCxh2YE=
=Ihh1
-----END PGP SIGNATURE-----

--nextPart1735617.YmkLPv5XtJ--

thanks a lot, I'll test it in my perf bench against other ways
joss
 
J

Josselin

I'd be more concerned with the multiple calls to #distance_to in the
original.

If there could be a lot of zoom levels (~50 or more), then it might
be worthwhile to replace the linear search with a binary search (giving
you only log2(N) tests to do rather than the full N), but with the small
number of zoom levels available in Google Maps, the extra complexity
likely isn't worth it.
yes, wich is not the case with GoogleMaps ;-))
I also wouldn't worry too much about performance unless this particular
piece of code is a measurable hot spot in your performance profile.
Otherwise, it's easy to tie yourself into knots worrying about the
performance of things which cannot have a significant impact on execution
time.

In the beginning, just focus on clarity and maintainability (which is what
DRY really speaks to): you'll often get a little performance improvement
and shorter code as side benefits without having to worry about either
directly.

-mental

thanks very useful advice...it's true that optimizing DB access
performances is my first objective,
I am trying then to look over some 're-du-plicated' lines or big loops
to avoid lengthy source code (as you say clarity and maintainability..
in this particular case, maybe the 6 lines are better for clarity to
anybody looking at the code later.... ;-)


joss
 

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

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top