Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The idea in these problems is to look at the code and figure out where you typed anything twice. When you see that, work to remove it. My program handles everything in your test data, and I don't have to repeat program logic structures to do it. That lets me focus on the data rather than program flow.</p> <p>First, let's clean up your tests. You really have a set of pairs that you want to test, so let's put them into a data structure. You can add or remove items from the data structure as you like, and the tests will automatically adjust:</p> <pre><code>use Test::More 'no_plan'; my @pairs = ( # got expect [ "1,234,567", 1234567 ], [ "1,234567", 1.234567 ], [ "1.234.567", 1234567 ], [ "1.234567", 1.234567 ], [ "12,345", 12345 ], [ "12,345,678", 12345678 ], [ "12,345.67", 12345.67 ], [ "12,34567", 12.34567 ], [ "12.34", 12.34 ], [ "12.345", 12345 ], # odd case! [ "12.345,67", 12345.67 ], [ "12.345.678", 12345678 ], [ "12.34567", 12.34567 ], [ "123,4567", 123.4567 ], [ "123.4567", 123.4567 ], [ "1234,567", 1234.567 ], [ "1234.567", 1234.567 ], [ "12345", 12345 ], [ "12345,67", 12345.67 ], [ "1234567", 1234567 ], ); </code></pre> <p>Now that you have it in a data structure, your long line of tests reduces to a short <code>foreach</code> loop:</p> <pre><code>foreach my $pair ( @pairs ) { my( $original, $expected ) = @$pair; my $got = parse_number( $original ); is( $got, $expected, "$original translates to $expected" ); } </code></pre> <p>The <code>parse_number</code> routine likewise condenses into this simple code. Your trick is to find out what you are doing over and over again in the source and not do that. Instead of trying to figure out weird calling conventions and long chains of conditionals, I normalize the data. I figure out which cases are odd, then turn them into not-odd cases. In this code, I condense all of the knowledge about the separators into a handful of regexes and return one of two possible lists to show me what the thousands separator and decimal separator are. Once I have that, I remove the thousands separator completely and make the decimal separator the full stop. As I find more cases, I merely add a regex that returns true for that case:</p> <pre><code>sub parse_number { my $string = shift; my( $separator, $decimal ) = do { local $_ = $string; if( /\.\d\d\d\./ || # two dots /\.\d\d\d,/ || # dot before comma /,\d{4,}/ || # comma with many following digits /\d{4,},/ || # comma with many leading digits /^\d{1,3}\.\d\d\d\z/ || # odd case of 123.456 0 ) { qw( . , ) } else { qw( , . ) } }; $string =~ s/\Q$separator//g; $string =~ s/\Q$decimal/./; $string; } </code></pre> <p>This is the sort of thing I talk about in the dynamic subroutines chapter of <a href="http://oreilly.com/catalog/9780596527242/" rel="nofollow noreferrer">Mastering Perl</a>. Although I won't go into it here, I would probably turn that series of regexes into a pipeline of some sort and use a grep.</p> <p>This is just the part of the program that passes your tests. I'd add another step to verify that the number is an expected format to deal with dirty data, but that's not so hard and is just a simple matter of programming. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload