suggest better trick to handle multiple hash keys

S

SSS Develop

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
 
J

J. Gleixner

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.
 
S

SSS Develop

Quoth SSS Develop <[email protected]>:


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.

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) = @_;


You should probably be using exists rather than defined.


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;
}

-------------
 
J

Jürgen Exner

SSS Develop said:
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
 

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,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top