Default value for uninitialized hash key - perl

Like in Perl, if a hash key is uninitialized then if you perform the below code
$hash{$key} =~ $hash{$key}++
then the value for that particular key increases to 1 (cause, it's first undefined and then as per the context, here it's numaical ... it takes the value to 0 ... increases it to 1).
My question is, does the same concept follows in case of C# as well? I mean, if I perform the above code in c# what would be the result? Will it be 1 or what?
Any idea?
Thanks,
Rahul

That bit of code makes no sense.
If you want to know if the key exists in the hash:
if (exists $hash{$key}) { ... }
If you want to know if it has a value defined:
if (defined $hash{$key}) { ... }
If you want to increment the value,
$hash{$key}++
As it is, you're attempting to do a regex match in a rather nonsensical way.

OOPS!!! Sorry ... I got it; actually the Perl code mentioned is meant to check/confirm whether the particular "KEY" exist or not ... OR sort of that.
So, in C# I cna just check for "hashtable.containskey(key)" ... that will do the trick.
Thanks.

Related

Perl Modification of a read-only value attempted for hash

I have a server that also counts the number of distinct IPs connected in a minute. I get a "Modification of a read-only value attempted" in the marked line in the code below:
$lsock=new IO::Socket::INET(LocalPort=>$port,Proto=>'tcp',Listen=>1,Reuse=>1);
$clients={};
while (1) {
$sock=$lsock->accept();
if ($sock) {
$clients->{$sock->peerhost()}=1; # THIS LINE !!!
...
}
}
# then later from an alarm signal I do:
sub save_stats {
my $cnt=scalar keys %$clients;
$clients={};
...
}
The error appears very rarely, once a month or less, but it's driving me insane, can someone please explain it to me why and what can I do?
After a lot of investigation I found the answer. It can happen that the connection is lost between accept() and peerhost(). In this case the peeerhost() function's return value is not suitable as a hash key. The solution is very simple, if peerhost() returns a "false" ignore the connection alltogether.

How can I get unique members per category using perl?

I used a hash to store members id. I avoid the duplicity using the following validation:
if($cases{$type} != $member_id) {
$cases{$type} = $member_id;
}
After that, I want to get the total of members by each $type. How can I do that?
I tried the following but do not work:
scalar(values $cases{$type});
Thanks a lot.
Your current approach doesn't actually count how many members are in a given type; it just keeps track of what the last member added is.
To keep a count, consider using a hash-of-a-hash; use this for each $member_id you're adding:
$cases{$type}{$member_id} = 1;
The value for the hash assignment doesn't matter; it's just a way to use hash keys to maintain uniqueness.
Then, to get the number of members for a given type, use
scalar keys %{$cases{$type}}
You could use $member_id as the key and use grep to find the count.
Store the $type like $case{$member_id} = $type
Use the following to print the count.
print scalar grep $case{$_} == $type, keys %case;

What is Perl DBI difference between with bind_columns and without it?

What is the difference between the following code in perl dbi?
1.
while (my ($p1, $p2, $p3) = $sth->fetchrow_array()) {
# ... some code ...
}
2.
$sth->bind_columns(\my ($p1, $p2, $p3));
while ($sth->fetch) {
# ... some code ...
}
Both leads to the same result.
Perlmonks advise on bind variant.
I would appreciate if someone explain why.
the docs says, that binding is more efficient way to fetch data:
The binding is performed at a low level using Perl aliasing. Whenever
a row is fetched from the database $var_to_bind appears to be
automatically updated simply because it now refers to the same memory
location as the corresponding column value. This makes using bound
variables very efficient.

Using hash as a reference is deprecated

I searched SO before asking this question, I am completely new to this and have no idea how to handle these errors. By this I mean Perl language.
When I put this
%name->{#id[$#id]} = $temp;
I get the error Using a hash as a reference is deprecated
I tried
$name{#id[$#id]} = $temp
but couldn't get any results back.
Any suggestions?
The correct way to access an element of hash %name is $name{'key'}. The syntax %name->{'key'} was valid in Perl v5.6 but has since been deprecated.
Similarly, to access the last element of array #id you should write $id[$#id] or, more simply, $id[-1].
Your second variation should work fine, and your inability to retrieve the value has an unrelated reason.
Write
$name{$id[-1]} = 'test';
and
print $name{$id[-1]};
will display test correctly
%name->{...}
has always been buggy. It doesn't do what it should do. As such, it now warns when you try to use it. The proper way to index a hash is
$name{...}
as you already believe.
Now, you say
$name{#id[$#id]}
doesn't work, but if so, it's because of an error somewhere else in the code. That code most definitely works
>perl -wE"#id = qw( a b c ); %name = ( a=>3, b=>4, c=>5 ); say $name{#id[$#id]};"
Scalar value #id[$#id] better written as $id[$#id] at -e line 1.
5
As the warning says, though, the proper way to index an array isn't
#id[...]
It's actually
$id[...]
Finally, the easiest way to get the last element of an array is to use index -1. The means your code should be
$name{ $id[-1] }
The popular answer is to just not dereference, but that's not correct. In other words %$hash_ref->{$key} and %$hash_ref{$key} are not interchangeable. The former is required to access a hash reference nested as an element in another hash reference.
For many moons it has been common place to nest hash references. In fact there are several modules that parse data and store it in this kind of data structure. Instantly depreciating the behavior without module updates was not a good thing. At times my data is trapped in a nested hash and the only way to get it is to do something like.
$new_hash_ref = $target_hash_ref->{$key1}
$new_hash_ref2 = $target_hash_ref->{$key2}
$new_hash_ref3 = $target_hash_ref->{$key3}
because I can't
foreach my $i(keys(%$target_hash_ref)) {
foreach(%$target_hash_ref->{$i} {
#do stuff with $_
}
}
anymore.
Yes the above is a little strange, but creating new variables just to avoid accessing a data structure in a certain way is worse. Am I missing something?
If you want one item from an array or hash use $. For a list of items use # and % respectively. Your use of # as a reference returned a list instead of an item which perl may have interpreted as a hash.
This code demonstrates your reference of a hash of arrays.
#!/usr/bin perl -w
my %these = ( 'first'=>101,
'second'=>102,
);
my #those = qw( first second );
print $these{$those[$#those]};
prints '102'

Where is my associative array and how do I access it using Perl DBI?

I'm working with perl, and using DBI. Up to now, I've been using ->fetchall_arrayref to get the results of a database query, and just accessing the array by numeric keys. However, I much prefer to be able to access records by the field names (associative fetch) than numeric.
How do I do this, and what is the correct syntax for accessing the keys?
I would prefer something like:
$data[0]['name']
Instead of:
$data[0][1]
Working Solution
my %data;
#{$data{$id}}{('name')} = 'something';
Read the DBI docs. Particularly, fetchall_hashref.
And you should also learn Perl syntax, as it's not the same as PHP.
You can use selectall_arrayref for this. Here's example from the DBI manpage:
You may often want to fetch an array of rows where each row is stored as a hash.
That can be done simple using:
my $emps = $dbh->selectall_arrayref(
"SELECT ename FROM emp ORDER BY ename",
{ Slice => {} }
);
foreach my $emp ( #$emps ) {
print "Employee: $emp->{ename}\n";
}
If you do fetchall_hashref() then you get the hash you are looking for. The keys will be the field names from the database. I am a little late, and Joe got it, but it will be.
$data->{0}->{'field'};