suggest better trick to handle multiple hash keys

Discussion in 'Perl Misc' started by SSS Develop, Oct 20, 2011.

  1. SSS Develop

    SSS Develop Guest

    Hello,

    I have customers information into database - the "cust_id" is one of
    the key. The cust_is not unique.
    I would like to create the hash as keys "cust_id" - but since they are
    not unique so problem.

    I am thinking of appending "_NUMBER" (example. cust001, cust001_0,
    cust001_1 ) whenever keys repeat.

    I have working code - but looking for help to better solution/better
    code. Please help me.

    --------------


    #!/usr/bin/perl
    use strict;
    use warnings;

    my $s = "cs011";
    my $customers = {};
    $s = generate_key( $s, $customers );
    print "The generated key is: $s\n";
    $customers->{$s} = 1;

    $s = generate_key( $s, $customers );
    print "The generated key is: $s\n";
    $customers->{$s} = 2;

    $s = generate_key( $s, $customers );
    print "The generated key is: $s\n";
    $customers->{$s} = 3;

    $s = generate_key( $s, $customers );
    print "The generated key is: $s\n";
    $customers->{$s} = 4;

    sub generate_key {
    if ( !defined $customers->{$s} ) { return $s; }
    else {
    if ( $s =~ /(.*)(_)(\d+$)/ ) {
    my $int = $3;
    $int++;
    $s = $1 . "_" . $int;
    }
    else { $s .= "_0"; }
    generate_key( $s, $customers );
    }
    }

    ----------------

    The output is:
    The generated key is: cs011
    The generated key is: cs011_0
    The generated key is: cs011_1
    The generated key is: cs011_2

    -------------


    thank you for your time !
     
    SSS Develop, Oct 20, 2011
    #1
    1. Advertising

  2. SSS Develop

    J. Gleixner Guest

    On 10/20/11 15:50, SSS Develop wrote:
    > Hello,
    >
    > I have customers information into database - the "cust_id" is one of
    > the key. The cust_is not unique.
    > I would like to create the hash as keys "cust_id" - but since they are
    > not unique so problem.


    First, why do you feel you want to use a hash?

    >
    > I am thinking of appending "_NUMBER" (example. cust001, cust001_0,
    > cust001_1 ) whenever keys repeat.


    You neglected to say what you are going to do with this field.
    If you're going to modify that value and eventually do some
    operations in the DB, then you have to rethink it because you'll
    lose the original value. If you're not going to do anything
    else with the DB, then do whatever you want with the data.

    Maybe rethinking your data structure is better??

    push( @{ $customer{ $s } }, 'some data' );

    or don't use a hash at all:

    push( @arr, $s );

    Look at using DBI, which will make interacting with a DB much easier.

    If you're going to do any further DB work, you'd be better off
    coming up with unique values for each row, e.g. adding ROWID, or
    using @rownum, or adding other columns in your SQL. If you can improve
    the table, by adding a unique column (auto increment, sequence, or
    something), you'll be better off in the future.



    >
    > I have working code - but looking for help to better solution/better
    > code. Please help me.
    >
    > --------------
    >
    >
    > #!/usr/bin/perl
    > use strict;
    > use warnings;
    >
    > my $s = "cs011";
    > my $customers = {};
    > $s = generate_key( $s, $customers );
    > print "The generated key is: $s\n";
    > $customers->{$s} = 1;

    Why set it to 1??
    [...]
    >
    > sub generate_key {

    ahhh.. you're passing $s and $customers to this sub, but
    you're using the global $s and $customers... not a good idea.

    This can be improved a bit, but since the data is coming from
    a DB, I question if it's even needed.

    > if ( !defined $customers->{$s} ) { return $s; }
    > else {
    > if ( $s =~ /(.*)(_)(\d+$)/ ) {
    > my $int = $3;
    > $int++;
    > $s = $1 . "_" . $int;
    > }
    > else { $s .= "_0"; }
    > generate_key( $s, $customers );
    > }
    > }
    >
    > ----------------
    >
    > The output is:
    > The generated key is: cs011
    > The generated key is: cs011_0
    > The generated key is: cs011_1
    > The generated key is: cs011_2
    >
    > -------------
    >
    >
    > thank you for your time !
    >
    >
     
    J. Gleixner, Oct 20, 2011
    #2
    1. Advertising

  3. SSS Develop

    SSS Develop Guest

    On Oct 20, 10:32 pm, Ben Morrow <> wrote:
    > Quoth SSS Develop <>:
    >
    >
    >
    > > I have  customers information into database - the "cust_id" is one of
    > > the key. The cust_is not unique.
    > > I would like to create the hash as keys "cust_id" - but since they are
    > > not unique so problem.

    >
    > What do these multiple records with the same cust_id represent? If you
    > actually have several customers with the same ID, how do you tell them
    > apart? If, instead, these multiple records are all referring to the same
    > customer, you want to keep them grouped together by customer rather than
    > faking a new cust_id.
    >
    > > I am thinking of appending   "_NUMBER" (example.  cust001, cust001_0,
    > > cust001_1 )  whenever keys repeat.

    >
    > Whenever you find yourself appending a number to something, like this,
    > you should be using an array. Instead of this
    >
    >     {
    >         cust001     => ...,
    >         cust001_0   => ...,
    >     }
    >
    > you should be using this
    >
    >     {
    >         cust001 => [
    >             ...,
    >             ...,
    >         ],
    >     }
    >


    [ssdevelop] - agree with you. By doing this - i will be forced to more
    work in other parts of the code. will definitely think of doing
    this.


    > <snip>
    >
    > >  #!/usr/bin/perl
    > > use strict;
    > > use warnings;

    >
    > > my $s         = "cs011";
    > > my $customers = {};
    > > $s = generate_key( $s, $customers );
    > > print "The generated key is: $s\n";
    > > $customers->{$s} = 1;

    > <snip>
    >
    > > sub generate_key {

    >
    > You aren't using the arguments you pass. This happens to work because
    > you're expecting the arguments to have the same names as the globals you
    > passed, but that's extremely fragile.
    >


    [sssdevelop] - my mistake, pasted small portion of the code her and
    forgot to add argument related part. adding new code here below:



    >     my ($s, $customers) = @_;
    >
    > >     if ( !defined $customers->{$s} ) { return $s; }

    >
    > You should probably be using exists rather than defined.
    >
    > >     else {
    > >         if ( $s =~ /(.*)(_)(\d+$)/ ) {
    > >             my $int = $3;
    > >             $int++;
    > >             $s = $1 . "_" . $int;
    > >         }
    > >         else { $s .= "_0"; }
    > >         generate_key( $s, $customers );

    >
    > Going round and round joining up a string and breaking it apart again is
    > rather a waste of time. Try
    >
    >         my $int = 0;
    >         while (exists $customers->{"$s_$int"}) {
    >             $int++;
    >         }
    >         $s .= "_$int";
    >
    > >     }

    >


    [sssdevelop] - helps, this is helpful suggestion.

    > You don't return $s either: the calling code is relying on the sub to
    > modify the global $s.
    >
    > Ben



    [sssdevelop] new code looks as below:

    -----------------------

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $s = "cs011";
    my $customers = {};
    $s = generate_key( $s, $customers );
    print "The generated key is: $s\n";

    $customers->{$s} = 1;

    $s = "cs011"; # Resetng key back to cs001
    $s = generate_key( $s, $customers );
    print "The generated key is: $s\n";

    $customers->{$s} = 2;

    $s = "cs011"; # Resetng key back to cs001
    $s = generate_key( $s, $customers );
    print "The generated key is: $s\n";

    $customers->{$s} = 3;

    $s = "cs011"; # Resetng key back to cs001
    $s = generate_key( $s, $customers );
    print "The generated key is: $s\n";


    sub generate_key {
    my ($string, $custhash) = @_;
    return $string unless defined $custhash->{$string};
    my $int = 0;
    while (exists $customers->{$string . "_" . $int}) {
    $int++;
    }
    return $string .= "_" . $int;
    }

    -------------
     
    SSS Develop, Oct 21, 2011
    #3
  4. SSS Develop <> wrote:
    >On Oct 20, 10:32 pm, Ben Morrow <> wrote:
    >> > I am thinking of appending   "_NUMBER" (example.  cust001, cust001_0,
    >> > cust001_1 )  whenever keys repeat.

    >>
    >> Whenever you find yourself appending a number to something, like this,
    >> you should be using an array. Instead of this

    >
    >[ssdevelop] - agree with you. By doing this - i will be forced to more
    >work in other parts of the code.


    Actually that is not true because an array allows you to index the
    values. Using individual variables you have to write

    DoSomeThingWith $cust001;
    DoSomeThingWith $cust001_1;
    DoSomeThingWith $cust001_2;
    DoSomeThingWith $cust001_3;
    DoSomeThingWith $cust001_4;
    DoSomeThingWith $cust001_5;
    ....

    while when using an array you can use a short

    foreach (@cust) {
    doDoSomeThingWith $_
    }

    and you don't even have to modify a single line when adding another
    element

    jue
     
    Jürgen Exner, Oct 21, 2011
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rp
    Replies:
    1
    Views:
    537
    red floyd
    Nov 10, 2011
  2. Xeno Campanoli
    Replies:
    16
    Views:
    268
    Martin DeMello
    Aug 25, 2005
  3. Alex Fenton

    Hash#values and Hash#keys order

    Alex Fenton, Apr 7, 2006, in forum: Ruby
    Replies:
    1
    Views:
    142
    George Ogata
    Apr 15, 2006
  4. Mage

    hash.keys and hash.values

    Mage, Aug 13, 2006, in forum: Ruby
    Replies:
    14
    Views:
    179
  5. Ronald Fischer

    Hash#keys, Hash#values order question

    Ronald Fischer, Aug 23, 2007, in forum: Ruby
    Replies:
    0
    Views:
    156
    Ronald Fischer
    Aug 23, 2007
Loading...

Share This Page