Hoping someone could explain the proper process for this. I have a data structure like this:
[
{
Author => "101",
WK1 => "",
WK10 => "",
WK11 => "",
WK12 => "",
WK13 => "",
WK14 => "X",
WK15 => "",
},
{
Author => "102",
WK1 => "",
WK10 => "",
WK11 => "",
WK12 => "X",
WK13 => "X",
WK14 => "",
WK15 => "",
WK2 => "X",
WK3 => "X",
WK4 => "",
},
{
Author => "101",
WK1 => "",
WK10 => "",
WK11 => "",
WK12 => "",
WK13 => "",
WK14 => "X",
WK15 => "X",
},
]
WK keys may or may not exist. The Author key will always exist, and I’m trying to merge those duplicates. Overwriting values is ok (if defined).
Should I try map (not sure how), or would it be better to create a new hash using the Author as key, pushing the other values into an array? Something like
foreach $x (#$data) {
%new_hash = ...
...
}
scratching head
It sounds like you are starting with something like the following:
my $records = [
{ Author => "101", WK1 => "", WK2 => "X", WK3 => "X" },
{ Author => "101", WK1 => "X", WK2 => "", WK4 => "X" },
{ Author => "102", WK1 => "", WK2 => "", WK3 => "X" },
];
It sounds like you want to produce the following:
my $records_by_author = (
"101" => { Author => "101", WK1 => "X", WK2 => "", WK3 => "X", WK4 => "X" },
"102" => { Author => "102", WK1 => "", WK2 => "", WK3 => "X" },
);
The following will do that:
my %records_by_author;
for my $record (#$records) {
my $author = $record->{Author};
$records_by_author{$author} = {
( $records_by_author{$author} ? %{ $records_by_author{$author} } : () ),
%$record,
};
}
If instead you want the following output:
my $records = [
{ Author => "101", WK1 => "X", WK2 => "", WK3 => "X", WK4 => "X" },
{ Author => "102", WK1 => "", WK2 => "", WK3 => "X" },
];
Just add the following:
$records = [ values(%records_by_author) ];
It you want this output and you want to preserve the original order, let me know.
I suggest merging along the lines of the code below. From each anonymous hash in #$data, grab the author identifier and then update the merged WK values where we never overwrite a non-empty string with an empty one.
You could do the same with map, and that would be a worthwhile exercise. It seems to read much more naturally as nested structural loops.
my %authorwk;
for (my $i = 0; #$data; ++$i) {
local $_ = shift #$data;
die "$0: missing Author in record $i" unless exists $_->{Author};
my $author = $_->{Author};
while (my($wk,$present) = each %$_) {
next unless $wk =~ /^WK/;
$authorwk{$author}{$wk} = $present
if $present || !exists $authorwk{$author}{$wk};
}
}
map is inappropriate here: a series of slice assignments is all that is necessary
It looks like this. Note that the only duplicate author 101 has an identical set of keys in both instances, so I've added key WK7 to the first instance and WK8 to the second so that you can see that they are both added to the result
use strict;
use warnings 'all';
my $data = [
{
Author => 101,
WK7 => "7", WK1 => "", WK10 => "", WK11 => "",
WK12 => "", WK13 => "", WK14 => "X", WK15 => "",
},
{
Author => 102,
WK1 => "", WK10 => "", WK11 => "", WK12 => "X",
WK13 => "X", WK14 => "", WK15 => "", WK2 => "X",
WK3 => "X", WK4 => "",
},
{
Author => 101,
WK8 => "8", WK1 => "", WK10 => "", WK11 => "",
WK12 => "", WK13 => "", WK14 => "X", WK15 => "X",
},
];
my %authors;
for my $item ( #$data ) {
my $author = $item->{Author};
#{ $authors{$author} }{keys %$item} = values %$item;
}
use Data::Dump;
dd \%authors;
output
{
101 => {
Author => 101,
WK1 => "",
WK10 => "",
WK11 => "",
WK12 => "",
WK13 => "",
WK14 => "X",
WK15 => "X",
WK7 => 7,
WK8 => 8,
},
102 => {
Author => 102,
WK1 => "",
WK10 => "",
WK11 => "",
WK12 => "X",
WK13 => "X",
WK14 => "",
WK15 => "",
WK2 => "X",
WK3 => "X",
WK4 => "",
},
}
Related
I've been trying to read the following structure in Perl:
my %Homes = (
"Home 1" => [
'TYPE_OF_HOUSE' => "Villa",
'FIELD1' => ["1","2","3"],
'Field2' => ["2","3","4"],
'Field3' => ["3","4","5"],
],
"Home 2" => [
'TYPE_OF_HOUSE' => "Duplex",
'FIELD1' => ["1","2","3"],
'Field2' => ["2","3","4"],
'Field3' => ["3","4","5"],
],
"Home 3" => [
'TYPE_OF_HOUSE' => "Apartment",
'FIELD1' => ["1","2","3"],
'Field2' => ["2","3","4"],
'Field3' => ["3","4","5"],
],
);
By using the following:
my #data_Array;
my ($inner_Key,$key,$names_ref);
foreach $key (keys %Homes)
{
print("Inner values of house $key are:");
foreach $inner_Key ( #{$Homes{$key}})
{
if ($inner_Key != "TYPE_OF_HOUSE")
{
$names_ref = \#$inner_Key;
#data_Array = #{$names_ref};
print($data_Array[0]);
print($data_Array[1]);
print($data_Array[2]);
}
else
{
print($inner_Key);
}
}
}
I successfully printed the: "Home 1", "Home 2", but when trying to read the inner content, even though I used reference to an array, it didn't go well. What did I miss? My goal was to "identify" the type of field, and if it was TYPE_OF_HOUSE, then simply print it because it is not an array. Otherwise, print the inner content of its array.
You must use strict and warnings because they will tell you a lot about what is wrong with your code.
You need to use ne instead of != when comparing strings.
You should use a different data structure to make it simpler to access inner data elements. You have a hash-of-arrays, but it would make more sense as a hash-of-hashes. By using => for 'TYPE_OF_HOUSE' => "Villa", you've tricked yourself into believing that is a hash. However, it is just a flat array. The 1st element of the array is TYPE_OF_HOUSE, the 2nd element is Villa, the 3rd is FIELD1, the 4th is an array ref, etc.
use warnings;
use strict;
my %Homes = (
"Home 1" => {
'TYPE_OF_HOUSE' => "Villa",
'FIELD1' => [ "1", "2", "3" ],
'Field2' => [ "2", "3", "4" ],
'Field3' => [ "3", "4", "5" ],
},
"Home 2" => {
'TYPE_OF_HOUSE' => "Duplex",
'FIELD1' => [ "1", "2", "3" ],
'Field2' => [ "2", "3", "4" ],
'Field3' => [ "3", "4", "5" ],
},
"Home 3" => {
'TYPE_OF_HOUSE' => "Apartment",
'FIELD1' => [ "1", "2", "3" ],
'Field2' => [ "2", "3", "4" ],
'Field3' => [ "3", "4", "5" ],
},
);
my #data_Array;
my ( $inner_Key, $key, $names_ref );
foreach $key ( keys %Homes ) {
print("Inner values of house $key are:");
print "\n";
foreach $inner_Key ( keys %{ $Homes{$key} } ) {
if ( $inner_Key ne "TYPE_OF_HOUSE" ) {
#data_Array = #{ $Homes{$key}{$inner_Key} };
print( $data_Array[0] );
print "\n";
print( $data_Array[1] );
print "\n";
print( $data_Array[2] );
print "\n";
}
else {
print($inner_Key);
print "\n";
}
}
}
I used perltidy to improve the indentation. I added newlines to make your print output easier to read.
In perl I can push $hashref into #array and have this data for next foreach and possible encode_json (HTTP POST).
I can't figure out how to recreate the same login in golang?
$VAR1 = [
{
'address' => 'test.com',
'id' => 101,
'hostgroups' => [
zero
'one',
'or many'
],
'host_name' => 'test.com',
'alias' => 'test.com',
'template' => 'generic',
'file_id' => 'etc/config'
},
{
'address' => 'test2.com',
'id' => 102,
'hostgroups' => [
zero
'one',
'or many'
],
'host_name' => 'test2.com',
'alias' => 'test2.com',
'template' => 'generic',
'file_id' => 'etc/config'
},
(..)
var array = []map[string]interface{}{
{"address": "test.com", "hostgroups": []string{"zero", "one", "or many"}, "id": 101},
{"address": "test2.com", "hostgroups": []string{"zero", "one", "or many"}, "id": 102},
}
This is the answer.
type host map[string]interface{}
var hosts []host
h := host{
"id": id,
"file_id": "etc/config/hosts.cfg",
"host_name": host_name,
"alias": host_name,
"address": host_name,
"hostgroups": hg,
"template": "generic-host",
}
hosts = append(hosts, h)
We currently process USD payments via paypal's REST API using their ruby gem. I would like to accept other currencies and have set our account to auto-convert foreign currency payments to USD. I can successfully process these payments and can see in the sandbox web interface that they were converted, but it's unclear to me how to look the conversion transactions up via the API. Can anyone shed any light on this? See screenshot and completed payment + sale record below.
Response[200]: OK, Duration: 0.858s
{
"id" => "PAY-0XK33729VB648561PKV5SG6A",
"intent" => "sale",
"payer" => {
"payment_method" => "paypal",
"status" => "VERIFIED",
"payer_info" => {
"email" => "jack#example.com",
"first_name" => "Fake",
"last_name" => "Fakerson",
"payer_id" => "F2JC8YDQ6HDUA",
"shipping_address" => {
"line1" => "1 Main St",
"city" => "San Jose",
"state" => "CA",
"postal_code" => "95131",
"country_code" => "US",
"recipient_name" => "Fake Fakerson"
}
}
},
"transactions" => [
[0] {
"amount" => {
"currency" => "EUR",
"total" => "5.00",
"details" => {
"subtotal" => "5.00"
}
},
"description" => "Unlimited School - I'm a course",
"related_resources" => [
[0] {
"sale" => {
"id" => "24439073LW446012K",
"amount" => {
"currency" => "EUR",
"total" => "5.00"
},
"payment_mode" => "INSTANT_TRANSFER",
"state" => "completed",
"protection_eligibility" => "ELIGIBLE",
"protection_eligibility_type" => "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE",
"transaction_fee" => {
"currency" => "EUR",
"value" => "0.50"
},
"parent_payment" => "PAY-0XK33729VB648561PKV5SG6A",
"create_time" => "2015-06-12T18:22:48Z",
"update_time" => "2015-06-12T18:23:19Z",
"links" => [
[0] {
"href" => "https://api.sandbox.paypal.com/v1/payments/sale/24439073LW446012K",
"rel" => "self",
"method" => "GET"
},
[1] {
"href" => "https://api.sandbox.paypal.com/v1/payments/sale/24439073LW446012K/refund",
"rel" => "refund",
"method" => "POST"
},
[2] {
"href" => "https://api.sandbox.paypal.com/v1/payments/payment/PAY-0XK33729VB648561PKV5SG6A",
"rel" => "parent_payment",
"method" => "GET"
}
]
}
}
]
}
],
"state" => "approved",
"create_time" => "2015-06-12T18:22:48Z",
"update_time" => "2015-06-12T18:23:19Z",
"links" => [
[0] {
"href" => "https://api.sandbox.paypal.com/v1/payments/payment/PAY-0XK33729VB648561PKV5SG6A",
"rel" => "self",
"method" => "GET"
}
]
}
I don't think so that REST API has any API for fetching the currency conversion only at this moment .
However , you can use the PayPal's Classic API to achieve your goal . See the example below :
NVP Request:
USER=XXXX&PWD=XXXXX&SIGNATURE=XXXXXXXX&VERSION=109.0&METHOD=TransactionSearch&STARTDATE=2014-06-01T00:00:00Z&ENDDATE=2015-06-05T00:00:00Z&TRANSACTIONCLASS=CurrencyConversions
NVP Response:
L_TIMESTAMP0=2015-04-21T20:53:39Z
L_TIMESTAMP1=2015-04-21T20:53:39Z
L_TIMESTAMP2=2014-11-11T18:40:45Z
L_TIMESTAMP3=2014-11-11T18:40:45Z
L_TIMEZONE0=GMT
L_TIMEZONE1=GMT
L_TIMEZONE2=GMT
L_TIMEZONE3=GMT
L_TYPE0=Currency Conversion (credit)
L_TYPE1=Currency Conversion (debit)
L_TYPE2=Currency Conversion (credit)
L_TYPE3=Currency Conversion (debit)
L_NAME0=From British Pound
L_NAME1=To U.S. Dollar
L_NAME2=From U.S. Dollar
L_NAME3=To British Pound
L_TRANSACTIONID0=76K70596XX6169325
L_TRANSACTIONID1=7P3811819E363281J
L_TRANSACTIONID2=2GF65791PP4273901
L_TRANSACTIONID3=2K135972TE2156124
L_STATUS0=Completed
L_STATUS1=Completed
L_STATUS2=Completed
L_STATUS3=Completed
L_AMT0=4060.54
L_AMT1=-2626.32
L_AMT2=6.36
L_AMT3=-10.36
L_CURRENCYCODE0=USD
L_CURRENCYCODE1=GBP
L_CURRENCYCODE2=GBP
L_CURRENCYCODE3=USD
L_FEEAMT0=0.00
L_FEEAMT1=0.00
L_FEEAMT2=0.00
L_FEEAMT3=0.00
L_NETAMT0=4060.54
L_NETAMT1=-2626.32
L_NETAMT2=6.36
L_NETAMT3=-10.36
TIMESTAMP=2015-06-12T22:48:14Z
CORRELATIONID=f01a7f7fb27f2
ACK=Success
VERSION=109.0
BUILD=16964802
I am writing a simple program that reads morse code from a file and converts it to plain text. I am getting some crazy errors though. I am not very familiar with perl and I am having to run it from command line. Below is the error that I am receiving and the code. It is possible that I am just running it wrong. I am typing: "perl -w Lott_Morse.pl morse.txt" into the command line. Any help would be appreciated.
Error:
Use of uninitialized value in print at Lott_CSC360_Morse2.pl line 31, <> line 7.
Use of uninitialized value in print at Lott_CSC360_Morse2.pl line 31, <> line 7.
Use of uninitialized value in print at Lott_CSC360_Morse2.pl line 31, <> line 7.
Use of uninitialized value in print at Lott_CSC360_Morse2.pl line 31, <> line 7.
Use of uninitialized value in print at Lott_CSC360_Morse2.pl line 31, <> line 7.
Use of uninitialized value in print at Lott_CSC360_Morse2.pl line 31, <> line 7.
The message is 0Jessicas-MacBook-Pro:Documents
Code:
#!/usr/bin/perl
use 5.010;
use warnings;
%morse_to_plain=(
".-" =>"A", "-..." => "B", "-.-." => "C", "-.." => "D", "." => "E",
"..-." => "F", "--." => "G", "...." => "H", ".." => "I", ".---" => "J",
"-.-" => "K", ".-.." => "L", "--" => "M", "-." => "N", "---" => "O",
".--." => "P", "--.-" => "Q", ".-." => "R", "..." => "S", "-" => "T",
"..-" => "U", "...-" => "V", ".--" => "W", "-..-" => "X", "-.--" => "Y",
"--.." => "Z", "-----" => "0", ".----" => "1", "..---" => "2", "...--" => "3",
"....-" => "4", "....." => "5", "-...." => "6", "--..." => "7", "---.." => "8",
"----." => "9", ".-.-.-" => ".", "--..--" => ",", "..--.." => "?", ".----." => "'",
"-....-" => "-", ".-..-." => '"', ".--.-." => "#", "-...-" => "=", "!" => " "
);
chomp(#message = <>);
print "The message is ";
foreach $char (#message)
{
print $morse_to_plain{$char};
}
You are reading in a string that does not have a matching key in your hash, so the hash value is undefined (uninitialized). It is likely an input problem. Try this for debugging purposes:
print $morse_to_plain{$char} // "Key does not exist: '$char'\n";
For longer strings, you might consider this:
$string =~ s{([-.]+)}{ $morse_to_plain{$1} // $1 }ge;
Which will search for combinations of dots and dashes and translate them to their text equivalent, or themselves if no translation is found.
You should also consider making your hash assignment a bit more readable:
my %morse_to_plain = (
".-" => "A", "-..." => "B", "-.-." => "C", "-.." => "D", "." => "E",
"..-." => "F", "--." => "G", "...." => "H", ".." => "I", ".---" => "J",
"-.-" => "K", ".-.." => "L", "--" => "M", "-." => "N", "---" => "O",
".--." => "P", "--.-" => "Q", ".-." => "R", "..." => "S", "-" => "T",
"..-" => "U", "...-" => "V", ".--" => "W", "-..-" => "X", "-.--" => "Y",
"--.." => "Z", "-----" => "0", ".----" => "1", "..---" => "2", "...--" => "3",
"....-" => "4", "....." => "5", "-...." => "6", "--..." => "7", "---.." => "8",
"----." => "9", ".-.-.-" => ".", "--..--" => ",", "..--.." => "?", ".----." => "'",
"-....-" => "-", ".-..-." => '"', ".--.-." => "#", "-...-" => "=", "!" => " "
);
It will make typos a lot easier to spot. Also, you can make the inverted lookup table rather easily:
my %plain_to_morse = reverse %morse_to_plain;
Remember to always use strict;. Worked well on multiple ... --- ... in a file (all the Morse code I know):
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
my %morse_to_plain=(
".-" =>"A", "-..." => "B", "-.-." => "C", "-.." => "D", "." => "E",
"..-." => "F", "--." => "G", "...." => "H", ".." => "I", ".---" => "J",
"-.-" => "K", ".-.." => "L", "--" => "M", "-." => "N", "---" => "O",
".--." => "P", "--.-" => "Q", ".-." => "R", "..." => "S", "-" => "T",
"..-" => "U", "...-" => "V", ".--" => "W", "-..-" => "X", "-.--" => "Y",
"--.." => "Z", "-----" => "0", ".----" => "1", "..---" => "2", "...--" => "3",
"....-" => "4", "....." => "5", "-...." => "6", "--..." => "7", "---.." => "8",
"----." => "9", ".-.-.-" => ".", "--..--" => ",", "..--.." => "?", ".----." => "'",
"-....-" => "-", ".-..-." => '"', ".--.-." => "#", "-...-" => "=", "!" => " "
);
print "The message is \n";
while (<>) {
chomp;
foreach my $char ( split ' ' ) {
print $morse_to_plain{$char};
}
print "\n";
}
I am just starting out with Perl and I am writing a program that reads a file and puts the morse code from that file into plain text in another file. I am getting this error and I cannot figure out what is wrong. Any help is appreciated!
Error I am receiving:
Jessicas-MacBook-Pro:Documents jessica$ perl -w Morse_to_Text.pl <Morse3.rtf> MorseTest.txt
Global symbol "$message" requires explicit package name at Morse_to_Text.pl line 20.
Global symbol "$message" requires explicit package name at Morse_to_Text.pl line 26.
Global symbol "$message" requires explicit package name at Morse_to_Text.pl line 26.
Global symbol "$message" requires explicit package name at Morse_to_Text.pl line 27.
Code:
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
my %morsecode=(
".-" =>"A", "-..." => "B", "-.-." => "C", "-.." => "D", "." => "E",
"..-." => "F", "--." => "G", "...." => "H", ".." => "I", ".---" => "J",
"-.-" => "K", ".-.." => "L", "--" => "M", "-." => "N", "---" => "O",
".--." => "P", "--.-" => "Q", ".-." => "R", "..." => "S", "-" => "T",
"..-" => "U", "...-" => "V", ".--" => "W", "-..-" => "X", "-.--" => "Y",
"--.." => "Z", "-----" => "0", ".----" => "1", "..---" => "2", "...--" => "3",
"....-" => "4", "....." => "5", "-...." => "6", "--..." => "7", "---.." => "8",
"----." => "9", ".-.-.-" => ".", "--..--" => ",", "..--.." => "?", ".----." => "'",
"-....-" => "-", ".-..-." => '"', ".--.-." => "#", "-...-" => "=", "!" => " "
);
while (<>) {
chomp;
foreach my $char ( split ' ' ) {
$message = $morsecode{$char} + $message;
print $message;
};
}
You use strict, so you should declare the global variable $message first. But as ikegami said in comment, use strict and warnings are one of the best practices when writing perl code. The pragmas catch many errors sooner that they would be caught otherwise, which makes it easier to find the root causes of the errors (just like the error you provide). The root cause might be the need for an error or validation check, and that can happen regardless or programmer skill.
I think what you want is the following code:
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
my %morsecode=(
".-" =>"A", "-..." => "B", "-.-." => "C", "-.." => "D", "." => "E",
"..-." => "F", "--." => "G", "...." => "H", ".." => "I", ".---" => "J",
"-.-" => "K", ".-.." => "L", "--" => "M", "-." => "N", "---" => "O",
".--." => "P", "--.-" => "Q", ".-." => "R", "..." => "S", "-" => "T",
"..-" => "U", "...-" => "V", ".--" => "W", "-..-" => "X", "-.--" => "Y",
"--.." => "Z", "-----" => "0", ".----" => "1", "..---" => "2", "...--" => "3",
"....-" => "4", "....." => "5", "-...." => "6", "--..." => "7", "---.." => "8",
"----." => "9", ".-.-.-" => ".", "--..--" => ",", "..--.." => "?", ".----." => "'",
"-....-" => "-", ".-..-." => '"', ".--.-." => "#", "-...-" => "=", "!" => " "
);
my $message;
while (<>) {
chomp;
foreach my $char ( split ' ' ) {
$message = $message.$morsecode{$char};
};
}
print $message."\n";
It means you didn't declare $message using my $message; where appropriate.
You might benefit from running your script using
perl -Mdiagnostics script.pl
It'll explain many warnings/errors.