maikelnight has asked for the wisdom of the Perl Monks concerning the following question:
Dear Monks,
beginner :-/ - i loop through an array and i want to give values out until the loop variable is something else. To be more clear:
foreach my $x (@cleared) {
my $jobprofil = $x->{JobProfil};
if (defined $jobprofil){
print $jobprofil, "\n";
}
else {
unless ($x =~ m/^Something/){
print "~~Something~~", $x, "\n";
}
}
}
This prints me ~~Something~~HereOutput
I tried to add:
else {
unless ($x =~ m/^Something Else/){
print "~~Something Else~~", $x, "\n";
}
}
But the result is not what i want. It prints:
~~Something Else~~HereOutput
~~Something~~HereOutput
~~Something~~HereOutput
~~Something~~HereOutput
~~Something~~HereOutput
How can i have my output printed like:
~~Something~~HereOutput
~~Something~~HereOutput
~~Something~~HereOutput
~~Something~~HereOutput
~~Something Else~~HereOutput
~~Something Else~~HereOutput
~~Something Else~~HereOutput
~~Something Else~~HereOutput
Re: Loop Array - If $var is something write values until $var is something else
by GrandFather (Saint) on Sep 29, 2018 at 23:32 UTC
|
I'm not sure what your "could be removed" string in the output is supposed to denote, but assuming that output string could be removed, the following may provide some ideas:
use strict;
use warnings;
my @cleared = (
'JOB::HEREISASTRING', 'Something',
'StringA', 'StringB',
'StringC', 'StringD',
'Something Else', 'StringE',
'StringF', 'StringG',
'StringH ', 'JOB::HEREISANOTHERSTRING',
'Something', 'StringI',
'StringJ', 'StringK',
'StringL', 'Something Else',
'StringM', 'StringN',
'StringO', 'StringP ',
);
my @result;
my $prefix = '~~Something~~';
foreach my $x (@cleared) {
if ($x =~ /JOB::(.*)/) {
$prefix = "";
}
elsif ($x =~ m/^Something Else/) {
$prefix = "~~Something Else~~";
}
elsif ($x =~ m/^Something/) {
$prefix = "~~Something~~";
}
print "$prefix$x\n";
}
Prints:
JOB::HEREISASTRING
~~Something~~Something
~~Something~~StringA
~~Something~~StringB
~~Something~~StringC
~~Something~~StringD
~~Something Else~~Something Else
~~Something Else~~StringE
~~Something Else~~StringF
~~Something Else~~StringG
~~Something Else~~StringH
JOB::HEREISANOTHERSTRING
~~Something~~Something
~~Something~~StringI
~~Something~~StringJ
~~Something~~StringK
~~Something~~StringL
~~Something Else~~Something Else
~~Something Else~~StringM
~~Something Else~~StringN
~~Something Else~~StringO
~~Something Else~~StringP
The trick is to use a "state" variable (in this case $prefix) to remember what state the parser is in. This is a trivial case of a state machine which can be used to simplify implementing many parsing and processing systems.
Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
| [reply] [d/l] [select] |
|
Dear All, thanks much for you input!
Dear GrandFather, the state variable is what i was after and i thought in that direction as i said. thank you. it solved my issue. Big ups!
| [reply] |
Re: Loop Array - If $var is something write values until $var is something else
by Marshall (Canon) on Sep 29, 2018 at 17:32 UTC
|
Hi maikelnight!,
First when you post a question here, the ideal situation is that you provide a completely runnable example including a sample of the data. That way I can just download the code into my Perl environment, push the "go button" and replicate exactly what you are seeing. update: Basically the easier you make it for the Monks to run your code, the more likely you are to get a prompt and good response. Right now I'd have to work my brain a bit to reverse engineer some data that would produce your results. Things are much better if I don't have to do that.
Do you have use strict; use warnings;? That is important. It looks like @cleared is an AoA (Array of Array), i.e. a 2-D structure. This code: ($x =~ m/^Something Else/) won't work because $x is a reference to an array. You need $x->[someIndex]to get a string to compare against. I am surprised if what you have doesn't throw some kind of an error? Why don't you rename $x, $row_ref or something like that? $x is not very descriptive.
This does look weird:
unless ($x =~ m/^Something Else/){
print "~~Something Else~~", $x, "\n";
}
That is the same as: print ~~Something Else~~ if $x is not Something Else , which is kinda weird.
if ($x->[someIndex] !~ m/^Something Else/){}
Does that help?
Enclose the output in code tags so that we can see the line breaks. | [reply] [d/l] [select] |
|
johngg@shiraz:~/perl/Monks$ perl -Mstrict -Mwarnings -E '
my @AoH = (
{ jobName => q{Director}, jobProfile => q{Three day week}, },
{ jobName => q{Manager}, jobProfile => q{9to5}, },
);
foreach my $job ( @AoH )
{
say $job;
say $job->{ jobProfile };
}'
HASH(0x562033e731e0)
Three day week
HASH(0x562033e92488)
9to5
I agree though that the unless ($x =~ m/^Something Else/){ does look weird as it would seem to be trying to match against a stringified reference. I suspect that we are not seeing the whole story.
| [reply] [d/l] [select] |
|
I agree. I misread the fonts between { and [ without my reading glasses! My dev environment has larger fonts than my browser!
In any event, these 2 code statements from the OP are inconsistent with the type of value of $x:
my $jobprofil = $x->{JobProfil};
...later this...
unless ($x =~ m/^Something Else/){
Something is wrong here. I am hoping that a full runnable code example with use strict; use warnings; will be very helpful. | [reply] [d/l] [select] |
|
|
|
|
|
|
|
Re: Loop Array - If $var is something write values until $var is something else
by AnomalousMonk (Archbishop) on Sep 29, 2018 at 19:32 UTC
|
maikelnight: Further to Marshall's post: Please see Short, Self-Contained, Correct Example. The monks grow sullen and silent when you make them do a lot of work in order to give free advice.
Others have noted that you don't seem to have warnings and strictures enabled. Let me repeat: Especially if you're a beginning Perler, always have the two statements
use warnings;
use strict;
at the beginning of your script. See (and use!) warnings and strict.
Finally, you seem confused about just what is in the @cleared array; we certainly are. Using some kind of data dumper can bring much enlightenment. Popular are Data::Dumper::Dump() (which is core and so should already be loaded in your system), and Data::Dump::dd() (which I like better, but it's not core, so you may have to load it yourself). Use one or the other
use Data::Dumper;
...
print Dumper \@cleared;
or
use Data::Dump;
...
dd \@cleared;
and you may find yourself much further down the road to a working application!
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
Sorry for confusing, should have removed the reference part as its not really important to my question. I removed it, use strict and warnings and now here is it:
my @result;
foreach my $x (@cleared) {
if ($x =~ /JOB::(.*)/){
print $x, "\n";
}
else {
unless ($x =~ m/^Something/){
print "~~Something~~", $x, "\n";
}
else {
unless ($x =~ m/^Something Else/){
print "~~Something Else~~", $x, "\n";
}
}
}
}
Lets see the @cleared (Dump):
$VAR1 = 'JOB::HEREISASTRING';
$VAR2 = 'Something';
$VAR3 = 'StringA';
$VAR4 = 'StringB';
$VAR5 = 'StringC';
$VAR6 = 'StringD';
$VAR7 = 'Something Else';
$VAR8 = 'StringE';
$VAR9 = 'StringF';
$VAR10 = 'StringG';
$VAR11 = 'StringH ';
$VAR12 = 'JOB::HEREISANOTHERSTRING';
$VAR13 = 'Something';
$VAR14 = 'StringI';
$VAR15 = 'StringJ';
$VAR16 = 'StringK';
$VAR17 = 'StringL';
$VAR18 = 'Something Else';
$VAR19 = 'StringM';
$VAR20 = 'StringN';
$VAR21 = 'StringO';
$VAR22 = 'StringP ';
Output:
JOB::HEREISASTRING
~~Something Else~~Something
~~Something~~StringA
~~Something~~StringB
~~Something~~StringC
~~Something~~StringD
~~Something~~Something Else
~~Something~~StringE
~~Something~~StringF
~~Something~~StringG
~~Something~~StringH
JOB::HEREISANOTHERSTRING
~~Something Else~~Something
~~Something~~StringI
~~Something~~StringJ
~~Something~~StringK
~~Something~~StringL
~~Something~~Something Else
~~Something~~StringM
~~Something~~StringN
~~Something~~StringO
~~Something~~StringP
I wish output:
JOB::HEREISASTRING
~~Something Else~~Something Else (could be removed)
~~Something~~StringA
~~Something~~StringB
~~Something~~StringC
~~Something~~StringD
~~Something Else~~Something Else (could be removed)
~~Something Else~~StringE
~~Something Else~~StringF
~~Something Else~~StringG
~~Something Else~~StringH
JOB::HEREISANOTHERSTRING
~~Something Else~~Something Else (could be removed)
~~Something~~StringI
~~Something~~StringJ
~~Something~~StringK
~~Something~~StringL
~~Something Else~~Something Else (could be removed)
~~Something Else~~StringM
~~Something Else~~StringN
~~Something Else~~StringO
~~Something Else~~StringP
In fact i want to tag my values from a start until a match occurs and tag it different and so on....
What comes to my mind is that with foreach loop variable $x changes and in the loop is again "Something"!? | [reply] [d/l] [select] |
|
You seem to want the flip-flop operator. Ref: Range Operators in perlop. A "state variable" is not needed because the state is stored in the operator.
?type 1223291.pl
use strict;
use warnings;
my @cleared = (
'JOB::HEREISASTRING',
'Something',
'StringA',
'StringB',
'StringC',
'StringD',
'Something Else',
'StringE',
'StringF',
'StringG',
'StringH ',
'JOB::HEREISANOTHERSTRING',
'Something',
'StringI',
'StringJ',
'StringK',
'StringL',
'Something Else',
'StringM',
'StringN',
'StringO',
'StringP ',
);
foreach (@cleared) {
if (/JOB::(.*)/){
print $_, "\n";
next;
}
print '~~Something';
if ( !(/Something$/ ... /Something Else$/) or /Else/) {
print ' Else';
}
print "~~$_\n";
}
?perl 1223291.pl
JOB::HEREISASTRING
~~Something~~Something
~~Something~~StringA
~~Something~~StringB
~~Something~~StringC
~~Something~~StringD
~~Something Else~~Something Else
~~Something Else~~StringE
~~Something Else~~StringF
~~Something Else~~StringG
~~Something Else~~StringH
JOB::HEREISANOTHERSTRING
~~Something~~Something
~~Something~~StringI
~~Something~~StringJ
~~Something~~StringK
~~Something~~StringL
~~Something Else~~Something Else
~~Something Else~~StringM
~~Something Else~~StringN
~~Something Else~~StringO
~~Something Else~~StringP
?
UPDATE: Added reference
| [reply] [d/l] |
Re: Loop Array - If $var is something write values until $var is something else
by davido (Cardinal) on Sep 29, 2018 at 19:21 UTC
|
my @cleared = (
'Something',
{JobProfil => undef},
{JobProfil => 1},
'Something else that should match',
'This one should not match',
);
Why are there hashrefs in some elements and not in others? Possibly the first test you should be doing is checking if $x contains a reference, at each iteration. Otherwise, you'll be trying to dereference $x as a hashref when it's actually just a plain old string. This would run afoul of strict 'refs';.
| [reply] [d/l] [select] |
|
|