How to print data by avoiding last comma - arrays

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

Related

How to pass multi-dimensional arrays through url as query parameters? and access these parameters in laravel 6.0

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

Add array to hash in perl

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.

Array output value is null on separating string value using implode function by comma output displays in exta comma? how to solve it?

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

creating hash of hashes in perl

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

unable to itherate through the array perl

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

Resources