1
\$\begingroup\$

I am trying to figure out how to DRY up this code:

nino = "QQ"
3.times { nino += Random.rand(10..99).to_s}
nino += ("A".."D").to_a.sample

I am trying to generate a sample National Insurance number starting with QQ, six digits and then ending with A, B, C or D.

\$\endgroup\$
6
\$\begingroup\$

Why do you need the 3 times? Is there a restriction, that the first number may not be 0?

If there is no 0-restriction, you may generate a number between 0 and 999999. To get the leading 0 I use the strftime-pattern %06i (6 digit with leading zeros).

  p "QQ%06i%s" % [ Random.rand(999999), ("A".."D").to_a.sample ]

For the letter, you may generate a random number from 65..68 and take the character for the selected ASCII-value (code example is ruby 1.9. Maybe you need a little variation with Ruby 1.8):

  p "QQ%06i%s" % [ Random.rand(999999), (65 + rand(4)).chr ]
\$\endgroup\$
2
\$\begingroup\$

If you mean more compact code, I though you can consider this:

nino = "QQ"<<(10..99).to_a.sample(3)*''<<("A".."D").to_a.sample
\$\endgroup\$
2
\$\begingroup\$

As Cygal says:

Also note that "DRY" in Code Review stands for "Don't Repeat Yourself", your title is thus a bit ambiguous.

If you are repeating implementing this logic through out your code then you should dry it up.

In my opinion this code has another problem. The purpose is not clear at a glance. Actually, one should process it in his mind to understand what's going on.

To prevent such a problem I suggest that:

  1. Encapsulate it in a method definition block with a suitable name that describes what it's doing (this way you will say what it's doing but not how it has implemented).
  2. Use a pattern or format to show how the result will look like. I am not familiar with Ruby but each language has its own way of doing it for example in C# we can use stirng.Format to define a format for our string:

    var result=String.Format("QQ{0}{1}{2}{3}",GetARandomNumber(),GetARandomNumber(),GetARandomNumber(),GetADigitBetween('A','D'));
    
\$\endgroup\$
  • \$\begingroup\$ As I responded to Cygal "Essentially my code is saying nino = blah, nino = nino + blahblah, nino = nino + blahblahblah; I am repeating myself three times which is why I was trying to not repeat myself." \$\endgroup\$ – ScottJShea Feb 27 '12 at 13:22
1
\$\begingroup\$

Disclaimer: I don't know Ruby but code in similar languages.

This looks "dried" enough to me. What would enhance readability though is to write this one simple line. It would show in a very explicit way that you are simply building one string (and would also make this shorter). Is it possible to make a one-liner out of this in Ruby?

Also note that "DRY" in Code Review stands for "Don't Repeat Yourself", your title is thus a bit ambiguous.

\$\endgroup\$
  • \$\begingroup\$ Essentially my code is saying nino = blah, nino = nino + blahblah, nino = nino + blahblahblah; I am repeating myself three times which is why I was trying to not repeat myself. \$\endgroup\$ – ScottJShea Feb 27 '12 at 13:21
1
\$\begingroup\$

Without leading zero's:

p "QQ#{rand(100_000..999_999)}#{%w(A B C D).sample}"
\$\endgroup\$
  • \$\begingroup\$ Actually in this case leading zeros were good but this would have been acceptable too. Thanks \$\endgroup\$ – ScottJShea Feb 28 '12 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.