I have this structure with data-dumper:
$VAR1 = {
'field' => [
{
'content' => {
'en' => [
'Footware haberdashery leather goods'
],
'de' => [
'Schuhe Kurzwaren und Lederartikel'
],
'it' => [
'Calzature mercerie e pelletterie'
]
},
'type' => 'tag',
'valore' => 'TAG3'
},
{
'content' => {
'en' => [
'Cobbler'
],
'de' => [
'Schuster'
],
'it' => [
'Calzolai'
]
},
'type' => 'tag',
'valore' => 'TAG24'
}
]
};
My question is: how to take data and print one for one ?
I want print the name, the tag and valore.
For my software is necessary take the name of shop and more data for example the type
It looks like the structure is a hashref containing an arrayref of hashes, and so on. And apparently where you mention 'name' you mean 'content' by language. Likewise, it seems that where you mention 'tag' you mean 'type'. My answer will be based on those assumptions.
foreach my $rec (#{$href->{field}}) {
print "$rec->{content}->{en}->[0]: $rec->{type}, $rec->{valore}\n";
}
The -> between {content} and {en}, and again between {en} and [0] are optional, and a matter of style.
If you simply want to access elements directly (foregoing the loop), you might do it like this:
print $href->{field}->[0]->{content}->{en}->[0], "\n";
print $href->{field}->[0]->{type}, "\n";
print $href->{field}->[0]->{valore}, "\n";
If you want to print all the languages, you could do this:
foreach my $rec (#{$href->{field}}) {
print $rec->{content}->{$_}->[0], "\n" foreach sort keys %{$rec->{content}};
print $rec->{type}, "\n";
print $rec->{valor}, "\n\n";
}
There are several Perl documentation pages that could be of use to you in the future as you learn to manipulate references and datastructures with Perl: perlreftut, perlref, and perldsc. Access them from your own system as perldoc perlreftut, for example.
Related
# data $bug
{
'keyword_objects' => [
bless( { 'id' => 15, 'name' => 'CRASH'}, 'SomeModule::SomeFilename' ),
bless( { 'id' => 6, 'name' => 'CUSTOMER' }, 'SomeModule::SomeFilename' ) ],
'category' => 'error'
}
foreach my $keyword ($bug->{keyword_objects}) {
print Dumper($keyword);
}
It prints the whole of keyword_objects instead of the individual items in it. Now it should be obvious to you that I know so little about Perl, I'd like to also ask what is the right way to reference name in each keyword.
To iterate over the elements in your array ref, you need to dereference it. foreach needs a list.
foreach my $keyword ( #{ $bug->{keyword_objects} } ) {
Your objects are hash references, so you could reach into their internals like this:
$keyword->{name}
However, messing with internals is not a good idea. Instead, you should write accessors and call them as a method.
$keyword->name
I have a complex json data structure in perl like in the following example. I want to address an array element and store data.
Variable
$VAR1 = {
'dummy' => 'foo',
'profiles' => {
'Tags' => [
{
'###PLACEHOLDER###',
}
],
}
I can for example add an element at "###PLACEHOLDER###" but want later in the perl script to add beneath that Placeholder additional information.
Normally i would address these elements with $var->{profiles}->{Tags}->{PLACEHOLDER} but this is not working with an array.
I dont want to create everytime a foreach loop when i know the name exactly.
Any advice?
[UPDATE: used dpathr instead of dpath for the references to structures]
[UPDATE: used dpath instead of dpathr for the references to elements]
Data::DPath can do what you require. Here's code which returns a reference to any structure (hash or array) which contains an element whose value is ###PLACEHOLDER###:
use strict;
use warnings;
use Data::Dumper;
use Data::DPath qw[ dpath dpathr ];
my $struct = {
'dummy' => 'foo',
'profiles' => {
'ARRAY' => [ '###PLACEHOLDER###' ],
'HASH' => { key => '###PLACEHOLDER###' },
},
};
my $path = dpath( '//[value eq "###PLACEHOLDER###"]/..' );
my #matches = $path->match( $struct );
print Dumper \#matches;
It results in:
$VAR1 = [
[
'###PLACEHOLDER###'
],
{
'key' => '###PLACEHOLDER###'
}
];
If you want direct access to the element, change the path to
my $path = dpathr( '//*[value eq "###PLACEHOLDER###"]' );
with the result:
$VAR1 = [
\'###PLACEHOLDER###',
\'###PLACEHOLDER###'
];
It's not clear to me what you what "adding an element at ###PLACEHOLDER###" means. Elements can be added to arrays and hashes, and it's not clear to which array or hash you are referring.
To append an element to the array referenced by $var->{profiles}{Tags}, use
push #{ $var->{profiles}{Tags} }, $val;
This results in
$VAR1 = {
'dummy' => 'foo',
'profiles' => {
'Tags' => [
{
'###PLACEHOLDER###' => undef,
},
$val
],
}
To add an element to the hash referenced by the last element of the array referenced by $var->{profiles}{Tags}, use
$var->{profiles}{Tags}[-1]{$key} = $val;
This results in
$VAR1 = {
'dummy' => 'foo',
'profiles' => {
'Tags' => [
{
'###PLACEHOLDER###' => undef,
$key => $val,
},
],
}
Of course, if $key is ###PLACEHOLDER###, this results in
$VAR1 = {
'dummy' => 'foo',
'profiles' => {
'Tags' => [
{
'###PLACEHOLDER###' => $val,
},
],
}
I'm using Lingua::TreeTagger for POS tagging, but its tagging just first word of string.
my $tagger = Lingua::TreeTagger->new(
'language' => 'english',
'options' => [ qw( -token -lemma -no-unknown ) ],
);
$text_to_tag = 'I another yet sample text I.';
my $tagged_text = $tagger->tag_text( \$text_to_tag );
print Dumper $tagged_text;
Output of the above dumper is as below:
'sequence' => [
bless( {
'is_SGML_tag' => 0,
'original' => 'I',
'tag' => 'PP',
'lemma' => 'I'
}, 'Lingua::TreeTagger::Token' )
],
Please note that only I is tagged here, but I want to tag whole sentence. In my actual code, I want to tag contents of a file. How can I tag all words of the sentence? Any help is appreciated.
using print Dumper my hash looks like
$VAR1 = {
'374' => {
'movies' => [ 'Harry potter 1', 'Harry potter 2'...],
'gender' => [ 'M' ],
'birthdate' => [ '1973/12/13' ], ...
}
When i try to access the fave movies element using
#infoName = 'movies';
foreach my $movie (#{$profile{$iD}{$infoName}}) {
print $movie;
}
I get the output '1979/08/29' etc which is the birthdate field?
Is it only accessing numerics or something?
How can i correctly print the movies from the hash?
It seems that your code you posted and your Dumper output is not properly related. If I try out your code like this:
use strict;
use Data::Dumper;
my %profile = (
"374" => {
'movies' => [ 'Harry Potter 1','Harry potter 2'],
'gender' => [ 'M' ],
'birthdate' => [ '1973/12/13' ],
}
);
print Dumper(\%profile);
print "----------\n";
my $iD = 374;
my $infoName = 'movies';
foreach my $movie (#{$profile{$iD}{$infoName}}) {
print $movie."\n"
}
it works perfectly and prints out:
$VAR1 = {
'374' => {
'birthdate' => [
'1973/12/13'
],
'movies' => [
'Harry Potter 1',
'Harry potter 2'
],
'gender' => [
'M'
]
}
};
----------
Harry Potter 1
Harry potter 2
So either your %profile hash is not really containing what the Dumper shows, or the code you posted does some additional stuff before it is processed by the foreach block.
If this doesn't solve your problem, I suggest posting a fully working small sample program which really demonstrates the problem.
I set up a user hash in a function with the following,
push #{$profile{$index}{$infoName}}, $information
and print it using print Dumper(\%profile); index++; in the function it was set up it prints each of indexes
`$VAR1 = { '374' => { 'degree' => [ 'CS' ], 'birthdate' => [ '1973/12/13' ], 'gender' => [ 'M' ],...}
$VAR1 = { '375' => { 'degree' => [ 'CS' ], 'birthdate' => [ '1933/02/03' ], 'gender' => [ 'F' ],...}`
when i try to access this within another function's foreach loop using print "${$profile{$currIndex}{'gender'}}"; i get odd behaviour where the print returns an empty string and get some random numbers appear in the hash: '$VAR1 = { '4' => {}, '1' => {}, '3' => {}, '2' => {}, '378' => { 'birthdate' => [ '1961/03/29' ], 'gender' => ['F'],..}
How can i properly access the gender feild from within a loop?
push #{$profile{$index}{$infoName}}, $information;
print "${$profile{$currIndex}{'gender'}}";
I'm not even sure what the second line actually does. On my Ubuntu, perl produces an error: not a scalar reference.
What you want is, to print all array elements:
print "#{$profile{$currIndex}{'gender'}}\n";
or, to print the first:
print $profile{$currIndex}->{'gender'}->[0], "\n";
The leaf element is an array references and has to be dereferenced as such.
I'm not sure why you use there array references. In your sample data there are no multiple elements in the arrays. Probably you wanted to write simply this? -
$profile{$index}{$infoName} = $information;
...
print "$profile{$currIndex}{'gender'}\n";