I try to add array in hash.
if ( not exists $hashtime{ $arr[0] }{ $date }{ $hour }{ $min } ) {
print "$min not exist";
$hashtime{ $arr[0] }{ $date }{ $hour }{ $min } = [ $sec ];
$create++;
};
And received the error:
Not a HASH reference at ./sort_log_by_ip.pl line 63, line 1.
Why is this code wrong?
In perldoc perldsc I see this construction, and I'm using something similar:
while ( <> ) {
next unless s/^(.*?):\s*//;
$HoA{$1} = [ split ];
}
Update
Code before:
if ( not exists $hashtime{ $arr[0] } ) {
$hashtime{ $arr[0] } = ( $date => { $hour => { $min => [ $sec ] } } );
$create++;
print "create for IP: $arr[0]\n";
}
if ( not exists $hashtime{ $arr[0] }{$date} ) {
$hashtime{ $arr[0] }{ $date } = ( $hour => { $min => [ $sec ] } );
$create++;
print "create for IP: $arr[0] DATE: $date\n";
}
if ( not exists $hashtime{ $arr[0] }{$date}{$hour} ) {
$hashtime{ $arr[0] }{ $date }{ $hour } = ( $min => [$sec] );
$create++;
print "create for IP: $arr[0] DATE: $date HOUR: $hour\n";
}
You are using a list ( ) instead of a hash reference { }, in all if blocks.
When you say
$hashtime{$arr[0]} = ( $date => { $hour => { $min => [$sec] } } );
because of LIST ( ) being evaluated in scalar context what happens is equivalent to
$hashtime{$arr[0]} = ( $date, { $hour => { $min => [$sec] } } );
ending up as
$hashtime{$arr[0]} = { $hour => { $min => [$sec] } };
since the , operator evaluates and discards operands one at a time, returning the last one.
The next if goes similarly and you then have either of (or both)
$hashtime{$arr[0]}{$date}{$min}{[$sec]}
$hashtime{$arr[0]}{$hour}{$min}{[$sec]}
However, the code that draws the error
if (not exists $hashtime{$arr[0]}{$date}{$hour})
needs a hashref at both $arr[0] and {$date}, while it clearly doesn't have both.
In both if blocks you need to assign a hash reference, obtained using { }
$hashtime{$arr[0]} = { $date => { $hour => { $min => [$sec] } } };
and
$hashtime{$arr[0]}{$date} = { $hour => { $min => [$sec] } };
as well as in the last if block.
Please indent your code properly. It is very hard to work with it the way it was posted.
Related
I have a data in my hash and trying to print them in the console.
Below is my script:
#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper;
my %hash = (
'2022-08-04' => {
'Method 1' => {
'Count' => 50,
'Size' => '10 MB'
},
'Method 2' => {
'Count' => 40,
'Size' => '5 MB'
}
},
'2022-08-05' => {
'Method 1' => {
'Count' => 30,
'Size' => '3 MB'
},
'Method 2' => {
'Size' => '50 MB',
'Count' => '100'
}
}
);
my #headers = ("Method 1", "Method 2");
my #headers_data;
push (#headers_data, "Date");
foreach (#headers) {
push(#headers_data, $_." Size", $_." Count");
}
print join(",", #headers_data);
print "\n";
for my $date ( sort keys( %hash ) ) {
my $by_method = $hash{$date};
print "$date,";
for my $method ( #headers ) {
my $rec = $by_method->{$method};
$rec->{Size} = $rec->{Size} ? $rec->{Size} : "NA";
$rec->{Count} = $rec->{Count} ? $rec->{Count} : "NA";
print "$rec->{Size},$rec->{Count},";
}
print "\n";
}
Here when I print in line print "$rec->{Size},$rec->{Count},";, this gives , at the end of the result which looks odd to me.
Example:
Date,Method 1 Size,Method 1 Count,Method 2 Size,Method 2 Count
2022-08-04,10 MB,50,5 MB,40,
2022-08-05,3 MB,30,50 MB,100,
You can see there is a comma(,) in line 2 and 3 of the result.
When I tried below logic (which is similar of printing #headers_data) I got stuck how to proceed with printing #data in the console, since it contains two days data together.
...
my #data;
for my $date ( sort keys( %hash ) ) {
my $by_method = $hash{$date};
push (#data, $date);
for my $method ( #headers ) {
my $rec = $by_method->{$method};
$rec->{Size} = $rec->{Size} ? $rec->{Size} : "NA";
$rec->{Count} = $rec->{Count} ? $rec->{Count} : "NA";
push (#data, $rec->{Size}, $rec->{Count});
}
}
Could someone please help me to print results like below:
Date,Method 1 Size,Method 1 Count,Method 2 Size,Method 2 Count
2022-08-04,10 MB,50,5 MB,40
2022-08-05,3 MB,30,50 MB,100
Modifying your first script:
...
for my $date ( sort keys( %hash ) ) {
my $by_method = $hash{$date};
my #line_data;
push #line_data, $date;
for my $method ( #headers ) {
my $rec = $by_method->{$method};
$rec->{Size} = $rec->{Size} ? $rec->{Size} : "NA";
$rec->{Count} = $rec->{Count} ? $rec->{Count} : "NA";
push(#line_data, $rec->{Size}, $rec->{Count});
}
print join(",", #line_data), "\n";
}
I am trying to pass a multi-dimensional array as a query parameter in the below URL:
{{serverURL}}/api/v1/classes?with[]=section.courseteacher&addl_slug_params[0][0]=test&addl_slug_params[0][1]=test1&addl_slug_params[0][2]=test0
what is wrong with the above URL?
My code to access these parameters in Laravel 6.0 is below:
$addl_slug_params = $request->query('addl_slug_params');
$i=0;
foreach ($addl_slug_params as $s) {
$j=0;
foreach($s as $asp) {
print_r('addl_slug_params : ('.$i.':'.$j.') : '.$asp); die();
$j=$j+1;
}
$i = $i+1;
}
Result:
addl_slug_params : (0:0) : test
Problem: test1 and test0 are not accessible..
What should I do?
The problem is the die(); after printr(), the loop will run once, aka only addl_slug_params : (0:0) : test
To help you visualize it better, I added an extra break after each loop:
foreach ($addl_slug_params as $s) {
$j=0;
foreach($s as $asp) {
echo('addl_slug_params : ('.$i.':'.$j.') : '.$asp);
echo nl2br(PHP_EOL);
$j=$j+1;
}
$i = $i+1;
}
Will result in the following:
addl_slug_params : (0:0) : test
addl_slug_params : (0:1) : test1
addl_slug_params : (0:2) : test0
here is a solution for multi-dimensional arrays. Developed in 2~ hours, definitely needs improvement but hopefully helps you out :)
Route::get('example', function (\Illuminate\Http\Request $request) {
$addl_slug_params = [
[
1 => [
'title' => 'Test 1',
'slug' => 'test1'
],
2 => [
'title' => 'Test 2',
'slug' => 'test2'
],
3 => [
'title' => 'Test 3',
'slug' => 'test3'
],
],
];
// Encode
$prepend = 'addl_slug_params';
$query = "?$prepend";
$tempSlugs = $addl_slug_params[0];
$lastIndex = count($tempSlugs);
foreach ($addl_slug_params as $pIndex => $params) {
foreach ($params as $sIndex => $slugData) {
$tempQuery = [];
foreach ($slugData as $sdIndex => $data) {
// Replace '-' or ' -' with ''
$encodedString = preg_replace('#[ -]+#', '-', $data);
// title = test1
$tempString = "$sdIndex=$encodedString";
$tempQuery[] = $tempString;
}
$dataQuery = implode(',', $tempQuery);
$appendStr = ($sIndex !== $lastIndex) ? "&$prepend" : '';
// Set the multidimensional structure here
$query .= "[$pIndex][$sIndex]=[$dataQuery]$appendStr";
}
}
// DECODE
// ?addl_slug_params[0][1]=[title=Test-1,slug=test1]&addl_slug_params[0][2]=[title=Test-2,slug=test2]&addl_slug_params[0][3]=[title=Test-3,slug=test3]
$slugParams = $request->query('addl_slug_params');
$slugParamData = [];
foreach ($slugParams as $slugItems) {
foreach ($slugItems as $slugItem) {
// Replace [title=test,slug=test1] into 'title=test,slug=test1' and explode
// into into an array, and split title=test into [title => test]
$splitArray = explode(',', (str_replace(array('[', ']'), '', $slugItem)));
$slugItemData = [];
foreach ($splitArray as $value) {
$data = explode('=', $value);
$slugItemData[$data[0]] = $data[1];
}
$slugParamData[] = $slugItemData;
}
}
dd($slugParamData);
});
I have solved the problem using associative arrays as it gives more flexibility and Garrett's solution definitely helped
new url: {{serverURL}}/api/v1/classes?with[]=section.courseteacher&addl[users][params]=name
laravel code:
`
foreach ($addl_data_array as $addl_slug => $addl_slug_data) {
foreach ($addl_slug_data as $key => $value) {
$params = null;
$where_raw = null;
$where_has = null;
$with_relationships = null;
$with_timestamps = null;
}
}
`
$drstring1 = stristr($drstring, 'DR', false);
//drupal_set_message($drstring1);
$drbrkstring = $drstring1;
$drval = explode('DR', $drbrkstring);
array_shift($drval);
$drdata_array = array();
foreach ($drval as $drv) {
$drdata = process_drstring('DR' . $drv);
$Colarray = array();
foreach ($drdata as $key => $value) {
array_push($Colarray, $key);
print 'key='. $key .' <br />';
}
$ColNames = implode(',' ,$Colarray);
print 'colunames=' .$ColNames.' <br />';
function process_drstring($string) {
$result = array();
$tag_text = array(
'DR' => 'segmenttag',
'01' => 'dateofentry',
'02' => 'dispute_remarks1',
'03' => 'dispute_remarks2',
'04' => 'dispute_remarks3',
'05' => 'dispute_remarks4',
'06' => 'dispute_remarks5',
'07' => 'dispute_remarks6',
);
$tag = substr($string, 0, 2);
$length = substr($string, 2, 2);
$data = substr($string, 4, $length);
$result[$tag_text[$tag]] = $data;
$newstring = substr($string, $length + 4, strlen($string));
if ($newstring) {
$newresult = process_drstring($newstring);
$result = array_merge($result, $newresult);
return $result;
}
else {
return $result;
}
}
output:
key=segmenttag
key=
key=dateofentry
key=dispute_remarks2
key=dispute_remarks1
key=dispute_remarks3
key=dispute_remarks4
key=dispute_remarks5
key=dispute_remarks6
colunames=segmenttag,,dateofentry,dispute_remarks2,dispute_remarks1,dispute_remarks3,dispute_remarks4,dispute_remarks5,dispute_remarks6
From this function , I need to get an columnames, but i'm receiving an extra key='' key element.
getting extra key value. Key='' it should not appear. Please help me solve this problem.
I have an array with contain values like
my #tmp = ('db::createParamDef xy', 'data $data1', 'model $model1', 'db::createParamDef wl', 'data $data2', 'model $model2')
I want to create a hash of hashes with values of xy and wl
my %hash;
my #val;
for my $file(#files){
for my $mod(#tmp){
if($mod=~ /db::createParamDef\s(\w+)/){
$hash{$file}="$1";
}
else{
my $value = split(/^\w+\s+/, $mod);
push (#val,$values);
}
$hash{$fname}{$1}="#val";
#val=();
}
}
this returns me only the filename and the value of $1, but i'm expecting output to be like this:
%hash=(
'filename1'=>
{
'xy'=>'$data1,$model1',
}
'filename2'=>
{
'wl'=>'$data2,$model2',
}
)
where am I doing wrong?!
This was actually a pretty tricky problem. Try something like this:
#!/bin/perl
use strict;
use warnings;
my #tmp = ('db::createParamDef xy', 'data $data1', 'model $model1', 'db::createParamDef wl', 'data $data2', 'model $model2');
my #files = ('filename1', 'filename2');
my %hash;
my #val;
my $index = 0;
my $current;
for my $mod (#tmp) {
if ( $mod=~ /db::createParamDef\s+(\w+)/){
$current = $1;
$hash{$files[$index]}={$current => ""};
$index++;
#val=();
} else {
my $value = (split(/\s+/, $mod))[1];
push (#val,$value);
}
$hash{$files[$index - 1]}{$current} = join(",", #val);
}
use Data::Dumper;
print Dumper \%hash;
Let me know if you have any questions about how it works!
my #tmp = (
'db::createParamDef xy', 'data $data1', 'model $model1',
'db::createParamDef wl', 'data $data2', 'model $model2'
);
my $count = 0;
my %hash = map {
my %r;
if (my($m) = $tmp[$_] =~ /db::createParamDef\s(\w+)/) {
my $i = $_;
my #vals = map { $tmp[$i+$_] =~ /(\S+)$/ } 1..2;
$r{"filename". ++$count}{$m} = join ",", #vals;
}
%r;
} 0 .. $#tmp;
use Data::Dumper; print Dumper \%hash;
output
$VAR1 = {
'filename1' => {
'xy' => '$data1,$model1'
},
'filename2' => {
'wl' => '$data2,$model2'
}
};
I have this perl script:
my %perMpPerMercHash;
foreach my $sheet () { #proper ranges specified
foreach my $row ( ) { #proper ranges specified
#required variables declared.
push(#{$perMpPerMercHash{join("-", $mercId, $mpId)}}, $mSku);
}
}
#Finally 'perMpPerMercHash' will be a hash of array`
foreach my $perMpPerMerc ( keys %perMpPerMercHash ) {
&genFile($perMpPerMerc, $perMpPerMercHash{$perMpPerMerc});
}
sub genFile {
my ( $outFileName, #skuArr ) = #_;
my $output = new IO::File(">$outFileName");
my $writer = new XML::Writer( OUTPUT => $output, DATA_MODE => 1, DATA_INDENT => 2);
#mpId is generated.
&prepareMessage($writer, $mpId, #skuArr);
}
sub prepareMessage {
my ( $writer, $mpId, #skuArr ) = #_;
my $count = 1;
print Dumper \#skuArr; #Printing correctly, 8-10 values.
foreach my $sku ( #skuArr ) { #not iterating.
print "loop run" , $sku, "\n"; #printed only once.
}
}
Can somebody please help why this is happening. I am new to perl and could not understand this anomaly.
EDIT:
output of Dumper:
$VAR1 = [
'A',
'B',
'C',
];
When you do
&genFile($perMpPerMerc, $perMpPerMercHash{$perMpPerMerc});
You're passing a reference to an array.
So in
sub genFile {
my ( $outFileName, #skuArr ) = #_;
You have to do :
sub genFile {
my ( $outFileName, $skuArr ) = #_;
and then use #$skuArr.
Have a look at references
The modified genFile sub will be:
sub genFile {
my ( $outFileName, $skuArr ) = #_;
my $output = new IO::File(">$outFileName");
my $writer = new XML::Writer( OUTPUT => $output, DATA_MODE => 1, DATA_INDENT => 2);
#mpId is generated.
&prepareMessage($writer, $mpId, #$skuArr);
}
And the other sub don't need to be modified.
Or you can pass always skuArr by reference:
&genFile($perMpPerMerc, $perMpPerMercHash{$perMpPerMerc});
...
sub genFile {
my ( $outFileName, $skuArr ) = #_;
...
&prepareMessage($writer, $mpId, $skuArr);
}
sub prepareMessage {
my ( $writer, $mpId, $skuArr ) = #_;
my $count = 1;
print Dumper $skuArr;
foreach my $sku ( #$skuArr ) {
print "loop run" , $sku, "\n";
}
}