Related
I have two arrays,says
$arraySel =array("1","Comment","LongText",
"2","Owners","Smalltext"
"3","Text","SmallText");
$arrayCurrent=array("1","Comment","LongText",
"2","Owners","Smalltext");
I need to compare these two arrays and i want to print the item which is nto exists in $arrayCurrent..I am working with PHP.
use array_diff() function :
$arraySel =array("1","Comment","LongText", "2","Owners","Smalltext", "3","Text","SmallText");
$arrayCurrent=array("1","Comment","LongText", "2","Owners","Smalltext");
$result=array_diff($arraySel,$arrayCurrent);
print_r($result);
output : Array ( [6] => 3 [7] => Text [8] => SmallText )
read more here : https://www.w3schools.com/php/func_array_diff.asp
I have the following request:
2017-04-05 06:53:31 Error: Cake\Http\ServerRequest Object
(
...
[_environment:protected] => Array
(
[HTTP_REGISTRATION] => eur73_9lhfQ:...SJMryPxCNzKcqSufdpFMOaux
...
)
[_detectorCache:protected] => Array
(
[ajax] =>
[get] => 1
[head] =>
[options] =>
[post] =>
)
[uri:protected] => Zend\Diactoros\Uri Object
(
[allowedSchemes:protected] => Array
(
[http] => 80
[https] => 443
)
...
)
...
)
$this->request->header['registration'] returns:
eur73_9lhfQ:...SJMryPxCNzKcqSufdpFMOaux
as string
$this->request->getHeader('registration') returns:
[Registration] => Array
(
[0] => eur73_9lhfQ:...SJMryPxCNzKcqSufdpFMOaux
)
Why does it return an array?
The HTTP standard allows multiple headers with the same field name to be present in case all values of that header can be expressed as a single, comma separated string (Set-Cookie is an exception to that rule, it cannot express multiple values in a single string, but in practice does still appear multiple times in order to define multiple cookies).
In order to support this in a convenient way, the PSR-7 standard (which \Cake\Http\ServerRequest complies to) defines the getHeader() method to return header values as arrays. The complement to that is the getHeaderLine() method, which is ment to return multiple values as a single, comma separated string.
See also
https://www.rfc-editor.org/rfc/rfc7230#section-3.2.2
http://www.php-fig.org/psr/psr-7/#headers-with-multiple-values
Further to finding an answer to my earlier question Perl: slicing an array of hashes, I am stuck again and unable to see what I have done wrong.
What I have is
Array( Array0(Hash0,Hash1),Array1(Hash0,Hash1),Array2(Hash0,Hash1)...)
use strict;
use warnings;
my #DDs = ();
my #Ds = ();
my %hsh = ();
my %dot1 = ( 'x' => 1, 'y' => 2, 'r' => 3 );
my %dot2 = ( 'x' => 4, 'y' => 5, 'r' => 6 );
my %dot3 = ( 'x' => 7, 'y' => 8, 'r' => 9 );
my %dot4 = ( 'x' => 1.1, 'y' => 1.2, 'r' => 1.3 );
my %dot5 = ( 'x' => 2.1, 'y' => 2.2, 'r' => 2.3 );
my %dot6 = ( 'x' => 3.1, 'y' => 3.2, 'r' => 3.3 );
my %dot7 = ( 'x' => 4.1, 'y' => 4.2, 'r' => 4.3 );
my %dot8 = ( 'x' => 5.1, 'y' => 5.2, 'r' => 5.3 );
my #dotsA = ( \%dot1, \%dot2 );
my #dotsB = ( \%dot3, \%dot4 );
my #dotsC = ( \%dot5, \%dot6 );
my #dotsD = ( \%dot7, \%dot8 );
my %Ds = ( \#dotsA, \#dotsB, \#dotsC, \#dotsD );
#DDs = $Ds[1]; #expect #dotsB with scalar of 2
###"Can't use an undefined value as HASH reference" error here
%hsh = %{ $DDs[0] }; #expect %dot3
print scalar #DDs, "\n"; #expect 2 but has value of 1
print $hsh{'x'}, "\n";
Reference found where even-sized list expected at /Users/schwern/tmp/test.plx line 10.
Line 10 is this:
my %dot1 = {'x'=>1,'y'=>2,'r'=>3};
This is Perl's cryptic way of saying you fed a hash reference to a hash. Perl, unfortunately, distinguishes very strongly between things and references to that thing.
%dot1 is a hash. It takes a list and turns it into a hash. A list like ( x => 1, y => 2, r => 3). { x => 1, y => 2, r => 3 } creates a hash reference. That's a single thing, a scalar. It's like saying my %dot1 = (42). It doesn't make any sense.
%dot1 is a hash, it wants a list like (x => 1, y => 2)
$dot1 is a scalar, it can store a hash reference like { x => 1, y => 2 }.
my %Ds = (\#dotsA,\#dotsB,\#dotsC,\#dotsD);
A hash requires a key and a value, pairs. last_name => "Schwern". When you give it a bunch of array references like that, it will read them as key1, value1, key2, value2... but what is it using as the key? It's using the stringification of that reference, something like ARRAY(0x7fb721800468).
If you asked for $D{\#dotsA} you'll get back a reference to #dotsB. You will not be able to get #dotsA back, a Perl hash key is just a string, not a reference.
This isn't a very good way to store an array in a hash. I'm not sure what you're trying to accomplish, but you probably want to reference them by name.
# A hash of lists.
my %Ds = ( A => \#dotsA, B => \#dotsB, C => \#dotsC, D => \#dotsD );
# Get back a reference to #dotsA.
my $dotsA = $Ds{A};
But looking at the following code, #DDs = $Ds[1];, I think you meant to initialize #Ds instead of %Ds.
#Ds = (\#dotsA,\#dotsB,\#dotsC,\#dotsD);
And now the following works... sort of. More later.
#DDs = $Ds[1]; #expect #dotsB with scalar of 2
Unlike in PHP, hashes and arrays are totally different things. my #Ds and my %Ds declare totally different variables. It doesn't help that you access them both with $Ds. In Perl5, the sigil indicates what's going to get returned. $Ds[1] and $Ds{foo} both use $Ds because they're returning a scalar. #Ds[1,2] and #Ds{(foo, bar)} use #Ds because they're returning a list (known as a slice). Confusing, but that's how it works.
#DDs = $Ds[1]; #expect #dotsB with scalar of 2
You're not getting #dotsB, you're getting a reference to #dotsB. All complex data structures in Perl store references, not the actual value. This is like $DDs[0] = \#dotsB. If you want to get the actual value you have to dereference it.
#DDs = #{$Ds[1]}; # Now #DDs has a copy of #dotsB
And finally it works.
#!/usr/bin/perl
use strict;
use warnings;
use v5.10; # for say()
my %dot1 = ('x'=>1,'y'=>2,'r'=>3);
my %dot2 = ('x'=>4,'y'=>5,'r'=>6);
my %dot3 = ('x'=>7,'y'=>8,'r'=>9);
my %dot4 = ('x'=>1.1,'y'=>1.2,'r'=>1.3);
my %dot5 = ('x'=>2.1,'y'=>2.2,'r'=>2.3);
my %dot6 = ('x'=>3.1,'y'=>3.2,'r'=>3.3);
my %dot7 = ('x'=>4.1,'y'=>4.2,'r'=>4.3);
my %dot8 = ('x'=>5.1,'y'=>5.2,'r'=>5.3);
my #dotsA = (\%dot1,\%dot2);
my #dotsB = (\%dot3,\%dot4);
my #dotsC = (\%dot5,\%dot6);
my #dotsD = (\%dot7,\%dot8);
my #Ds = (\#dotsA,\#dotsB,\#dotsC,\#dotsD);
my #DDs = #{$Ds[1]}; #expect #dotsB
my %hsh = %{$DDs[0]}; #expect %dot3
say scalar #DDs; #expect 2
say $hsh{'x'};
I would also advise that you get comfortable working directly with references since that's what complex data structures are: references. Converting back and forth from references to values is confusing. Working with references is one less thing to convert in your code, in your head, and less copying done in your program.
#!/usr/bin/perl
use strict;
use warnings;
use v5.10; # for say()
my $dot1 = {'x'=>1,'y'=>2,'r'=>3};
my $dot2 = {'x'=>4,'y'=>5,'r'=>6};
my $dot3 = {'x'=>7,'y'=>8,'r'=>9};
my $dot4 = {'x'=>1.1,'y'=>1.2,'r'=>1.3};
my $dot5 = {'x'=>2.1,'y'=>2.2,'r'=>2.3};
my $dot6 = {'x'=>3.1,'y'=>3.2,'r'=>3.3};
my $dot7 = {'x'=>4.1,'y'=>4.2,'r'=>4.3};
my $dot8 = {'x'=>5.1,'y'=>5.2,'r'=>5.3};
my $dotsA = [$dot1,$dot2];
my $dotsB = [$dot3,$dot4];
my $dotsC = [$dot5,$dot6];
my $dotsD = [$dot7,$dot8];
my $Ds = [$dotsA,$dotsB,$dotsC,$dotsD];
my $DDs = $Ds->[1]; #expect $dotsB
my $hsh = $DDs->[0]; #expect $dot3
say scalar #$DDs; #expect 2
say $hsh->{'x'};
You should review perlreftut and the Nested Data Structures chapter of Modern Perl.
I am trying to calculate distance between two geographical locations. one location is entered by user.
User entered location is calculated by model and is stored in the variable.
$ulatitude=$userLocation['Location']['latitude'];
$ulongitude=$userLocation['Location']['longitude'];
I have used below code to calculate the distance.
$this->User->virtualFields['lowestDistance'] = 'round(3959 * acos(cos(radians($ulatitude)) * cos(radians(Profile.latitude )) * cos(radians(Profile.longitude) - radians($ulongitude)) + sin(radians($ulatitude)) * sin(radians(Profile.latitude)))) ';
$order = "User.lowestDistance";
$options = array(
'fields' => '
User.*, Profile.*,
round(3959 * acos(cos(radians($ulatitude)) * cos(radians(Profile.latitude )) * cos(radians(Profile.longitude) - radians($ulongitude)) + sin(radians($ulatitude)) * sin(radians(Profile.latitude)))) AS lowestDistance,
',
'order' => array($order =>'asc'),
);
Above code throws error : unknown column $ulatitude.
Is there any other way of doing this ?
Single quotes are not interpreted
Consider:
<?php
$foo = "A VARIABLE";
echo 'foo is $foo' . "\n";
echo "foo is $foo" . "\n";
This would output:
-> php example.php
foo is $foo
foo is A VARIABLE
In the question everything is in single quotes, they are literal strings.
Fields should be an array
Also note that this:
'fields' => 'User.*, Profile.*, ...
Is normally an array, which makes more sense when there's multiple values:
'fields' => [
'User.*',
'Profile.*',
...
]
But since you're declaring all fields plus a virtual field, it'd be included in a find call anyway - just remove the fields from the find parameters:
$this->User->virtualFields['lowestDistance'] = "round(...";
$options = [
//'fields' => [], Not necessary
'order' => [$order =>'asc']
];
$withLowestDistance = $this->User->find('all', $options);
I have the following data in a hash of hash of arrays. The numerical data in the array represents that last 4 quarters of financial information.
I'd like to be able to iterate over the array, and pull out the data by quarter, to get it ready to insert into a database. With my code below I can get all of the quarters, or one quarter only if I specifically call it. When I try and add another loop to iterate over the hash of hash of arrays to return only the array subset values, i get all the values and I don't know what I'm doing wrong. See code: Thanks for the help
my %comp_info = (
CompanyA => {
COGS => ["175.00", "155.00", "125.00", "125.00"],
Revenue => ["300.00", "200.00", "250.00", "225.00"],
},
)
# The following works, but I have to specifically push one array subset at a time,
# which makes passing values to db_insert subroutine ineffective.
# (Id have to have 4 or 5 calls depending on number of quarters of data in each record).
sub get_insert_arrays {
foreach $comp (keys %comp_info ) {
foreach $column ( keys %{$comp_info{$comp}} ) {
push (#insert_array, #{$comp_info{$sym}{$column}}[0] );
}
}
my $valuelist = join(", ", #insert_array);
&db_insert($valuelist);
undef #insert_array;
}
#try to loop through, fails, I get all of the data in #insert_array instead of only one quarter.
sub get_insert_arrays {
foreach $comp (keys %comp_info ) {
foreach $column ( keys %{$comp_info{$comp}} ) {
for my $i ( 0 .. $#{$comp_info{$comp}{$column}} ) {
push (#insert_array, #{$comp_info{$sym}{$column}}[$i] );
}
}
my $valuelist = join(", ", #insert_array);
&db_insert($valuelist);
undef #insert_array;
undef $valuelist;
}
}
I highly recommend to dereference with intermediate variables, and also using the -> syntax. Both of these help you figure out what's going on:
Here's your first subroutine using dereferencing:
sub get_insert_arrays {
my #insert_array;
foreach $comp (keys %comp_info ) { # References to a hash (Revenue, COGS)
%columns = %{ $comp_info{$comp} }; # Dereference
foreach $column ( keys %columns ) { # Reference to an Array (quarter data)
my #values = #{ $column } ; # Dereference
push (#insert_array, $column );
my $valuelist = join(", ", #insert_array);
&db_insert($valuelist);
}
}
}
Hmm... Looking at this, it's easy to see that I can simply do:
for my $comp (keys %comp_info ) { # References to a hash (Revenue, COGS)
%columns = %{ $comp_info{$comp} }; # Dereference
for my $column ( keys %columns ) { # Reference to an Array (quarter data)
my #values = #{ $column } ; # Dereference
db_insert(#values);
}
}
}
If you need to see a particular piece of data, use the -> syntax to simplify your structure:
${$comp_info{$sym}{$column}}[$i]; # You had "#". Should be "$".
vs.
$comp_info{$sym}->{$column}->[$i];
Much easier to read.
Also use the warnings and strict pragmas in your program. It'll catch a lot of errors that may include undefined variables, and misspelled variable names.
If you're pulling out data quarter-by-quarter, you probably want the COGS to be with the Revenue column:
#! /usr/bin/env perl
#
use strict; # Lets you know when you misspell variable names
use warnings; # Warns of issues (using undefined variables
use feature qw(say);
#
# Just initializing the data you had
#
my %comp_info = ( CompanyA => {
Revenue => [
300.00, 200.00, 250.00, 225.00
],
COGS => [
175.00, 155.00, 125.00, 125.00
],
},
);
#
# Go through each company
#
for my $company ( keys %comp_info ) {
my #revenues = #{ $comp_info{$company}->{Revenue} }; # Dereference
my #cogss = #{ $comp_info{$company}->{COGS} }; # Dereferenec
say "Company: $company";
#
# I know the keys are "Revenue" and "COGS", so I don't need a loop.
# I'll just go right to my quarters data. Note that dereferencing
# makes my program a lot easier to write and maintain
#
for my $quarter ( (0..3) ) {
my $revenue = $revenues[$quarter];
my $cogs = $cogss[$quarter];
my $profit = $revenue - $cogs;
say " Quarter: " . ($quarter - 1)
. " Revenue = $revenue COGS = $cogs Profit = $profit";
}
}
How you do your database inserts is up to you. But, you can see how doing a bit of dereferencing and using -> can clarify what you're looking at.
Addendum
how do I pull out just the quarter by quarter data without having to specify revenue, cogs, etc. in some cases there could be 30+ fields, so I don't want to have to specify each field in the program. I just want to grab all Q1 fields, insert, grab all Q2 field, insert, etc.
So two loops:
Like before, I have my outer loop go through for each company which just happens to be the key for that %comp_info hash.
Each value in the %comp_info hash is a reference to another hash that is keyed by the data type (COGS, Revenue, etc.). Again, I simply loop through the keys of that inner hash (after dereferencing to make it easier to understand).
Now that I have the company name (the key to that %comp_info hash, and a list of the keys in that inner hash, I can simply pull up the first quarter numbers for each company and each data type. Getting the quarter value is simple: $comp_info{$company}->{$type}->[$quarter]. Note that there is three levels of data, and I have three sections in my variable with each section separated by ->.
I can see that the outer most section is a simple hash that's keyed by the company name: ($comp_info{$company}).
This %comp_info hash points to a hash reference (->{type}) which is keyed by the data types (COGS, Revenue, etc.).
And that hash reference points to an array reference for each quarter (->[$quarter]). See how that works and why I like that -> syntax? It makes it very clear what I am working with.
This is just the first quarter results. If I wanted to go through each and every quarter, I could have an outer loop for my $quarter (0..3) {.
Here's what it looks like. This is a complete program, so you could cut this out, and try running it yourself and see if you can figure out what's going on.
use strict; # Lets you know when you misspell variable names
use warnings; # Warns of issues (using undefined variables
use feature qw(say);
my $quarter = 0; #First Quarter is 0. Last quarter is 3
my %comp_info = ( CompanyA => {
Revenue => [
300.00, 200.00, 250.00, 225.00
],
COGS => [
175.00, 155.00, 125.00, 125.00
],
},
);
for my $company ( keys %comp_info ) {
say "Company: $company";
%types = %{ $company_info{$company} };
for my $type ( keys %types ) { # COGS, Revenue, etc.
say " $type for quarter "
. ($quarter + 1) . ": "
. $comp_info{$company}->{$type}->[$quarter];
}
}
One more time for each quarter to insert the data into your database:
Using use strict and declaring variables with my means that variables are only valid for a limited scope. That my #type_data; declares a array that holds my type values for inserting into your database. However, since it's declared inside that for my $quarter loop, the array and its values disappears with each iteration of the loop. No need to have to remove the data or reinitialize the variable. It does it all by itself!
Look up how Lexically Scoped Variables work.
for my $quarter ( (0..3) ) {
my #type_values;
for my $company ( keys %comp_info ) {
my %types = %{ $comp_info{$company} };
for my $type ( keys %types ) { # COGS, Revenue, etc.
push #type_values, $comp_info->{$company}->{$type}->{quarter};
}
insert_data( #type_values ); # Database insert you wanted
}
Your recent addition - undef #insert_array; undef $valuelist; is a misuse of undef. Putting it before a variable like that forces a garbage collection cycle, which is something you don't want to do -- it is best to let Perl look after things itself.
Arrays should be emptied with #insert_array = () rather than using undef, and for scalars you should $valuelist = undef. But these variables are irrelevant outside the subroutine, so you should declare them inside, in which case there is no need to reinitialise them in the first place.
Please bear in mind what I said about calling prepare on an SQL statement with placeholders. Your code should look something like this
my $insert = $dbh->prepare('INSERT INTO table VALUES (?, ?)');
and later
my #insert_array = (175.00, 300.00);
$insert->execute(#insert_array);
However I have written this, which I think does what you want, to create a $valuelist string as your own code does. Since you don't need the hash keys, it is much tidier to iterate over the values instead. The db_insert subroutine is a dummy that just prints the values of the parameter passed to it.
use strict;
use warnings;
use 5.010;
my %comp_info = (
CompanyA => {
COGS => ["175.00", "155.00", "125.00", "125.00"],
Revenue => ["300.00", "200.00", "250.00", "225.00"],
},
);
my #values = map values %$_, values %comp_info;
for my $i (0 .. $#{$values[0]}) {
my #insert = map $_->[$i], #values;
db_insert(join ', ', #insert);
}
sub db_insert {
say "db_insert('#_')";
}
output
db_insert('175.00, 300.00')
db_insert('155.00, 200.00')
db_insert('125.00, 250.00')
db_insert('125.00, 225.00')
Update
To comply with the new specification:
use strict;
use warnings;
use 5.010;
my %comp_info = (
CompanyA => {
COGS => ["175.00", "155.00", "125.00", "125.00"],
Revenue => ["300.00", "200.00", "250.00", "225.00"],
},
CompanyB => {
COGS => ["175.00", "155.00", "125.00", "125.00"],
Revenue => ["300.00", "200.00", "250.00", "225.00"],
},
CompanyC => {
COGS => ["175.00", "155.00", "125.00", "125.00"],
Revenue => ["300.00", "200.00", "250.00", "225.00"],
},
);
my #columns = qw/ COGS Revenue /;
for my $comp (keys %comp_info) {
my $data = $comp_info{$comp};
for my $i (0 .. $#{(values %$data)[0]}) {
my #values = ( $comp, map $_->[$i], #{$data}{#columns} );
db_insert(join ', ', #values);
}
}
sub db_insert {
say "db_insert('#_')";
}
output
db_insert('CompanyC, 175.00, 300.00')
db_insert('CompanyC, 155.00, 200.00')
db_insert('CompanyC, 125.00, 250.00')
db_insert('CompanyC, 125.00, 225.00')
db_insert('CompanyA, 175.00, 300.00')
db_insert('CompanyA, 155.00, 200.00')
db_insert('CompanyA, 125.00, 250.00')
db_insert('CompanyA, 125.00, 225.00')
db_insert('CompanyB, 175.00, 300.00')
db_insert('CompanyB, 155.00, 200.00')
db_insert('CompanyB, 125.00, 250.00')
db_insert('CompanyB, 125.00, 225.00')