Hi I have a simple question: how do I iterate through an array. The array below contains strings to be modified through a regex command.
foreach(#array)
{
$count = 0;
#array[$count] =~ /regex here../;
$count++;
}
I am able to modify the first object in the array but not the rest. Any help would be appreciated. Thanks
Simply :
foreach(#array)
{
/regex here../;
}
or
foreach my $a (#array)
{
$a =~ /regex here../;
}
or
foreach my $i (0 .. $#array)
{
$array[$i] =~ /regex here.../;
}
Related
I want to use $i value in #array_mem_depth_$i so that my dynamically created arrays look like #array_mem_depth_1024,#array_mem_depth_512.
How to achieve this?
while(<FH>) {
$line = $_;
chomp($line);
foreach my $i (#depth_uarr) { if ( $line =~ /$i/) {push (#array_mem_depth_${i}, $line);} }
}
Thanks
I would not actually recommend having variables with dynamic names. While this might be technically feasible, this would make your code far more complex, for no obvious benefit.
Instead, why not have a hash of array references. Based on your partial code, this would look like:
my %h;
while(my $line = <FH>) {
chomp($line);
foreach my $i (#depth_uarr) {
if ( $line =~ /$i/ ) {
push #{ $h{$i} }, $line;
}
}
}
I have the associative array %cart_item, within this is a series of associative arrays. I need to access the value of the keys within %cart_item. I have the following code which iterates on each array key. (I do the equivalent of php's continue if the value is 'meta')
my $key_value;
for (keys %cart_item) {
next if (/^meta$/ || /^\s*$/);
}
I need to do something like this though (although this isn't valid), setting the value of the keys in the loop:
my $key_value;
for $i (keys %cart_item) {
next if (/^meta$/ || /^\s*$/);
$key_value = $i;
# do stuff
}
Could anyone suggest a solution here? Apologies if this is obvious, I'm a Perl newbie. Thanks
I think you are asking for
for my $key (keys %cart_item) {
next if $key =~ /^meta$/ || $key =~ /^\s*$/;
my $val = $cart_item{$key};
...
}
If you're just looking for the value that goes with the key, you can get both at the same time with each:
while (my ($key, $val) = each %cart_item) {
next if $key eq 'meta' || $key =~ /^\s*$/;
...
}
That's the equivalent of PHP's foreach ($cart_item as $key => $val).
I also changed the "meta" check to use simple string equality; no need to use a regular expression for an exact match.
Your original code has
for ( keys %cart_item ) {
next if (/^meta$/ || /^\s*$/);
}
which works fine because the for has no loop control variable so it defaults to Perl's "pronoun" it variable $_. In addition, your regex pattern matches have no object so they also default to $_
Written fully, this would be
for $_ ( keys %cart_item ) {
next if ( $_ =~ /^meta$/ || $+ =~ /^\s*$/);
}
but we don't have to write all of that. Some people hate it; others like me think it's absolute genius
Your non-working code
my $key_value;
for $i (keys %cart_item) {
next if (/^meta$/ || /^\s*$/);
$key_value = $i;
# do stuff
}
does use a loop control control variable $i (bad name for a hash key, by the way). That's all fine except that your regex matches still
my $key_value;
for $i (keys %cart_item) {
next if $i =~ /^meta$/ or $i =~ /^\s*$/;
$key_value = $i;
# do stuff
}
or, better still, stick with $_ and write this
for ( keys %cart_item ) {
next if /^meta$/ or /^\s*$/;
my $key_value = $_;
# do stuff
}
Here's how I've set up my hash:
my #keys_i_need = qw(A B C D E F G);
my %keys_i_need = map {$_ => []} #keys_i_need;
foreach my $line (#{$file_arr_ref}) {
my $sub = substr( $line, 0, 1);
if(($sub ne "#") and ($sub ne "")){
my #key_vals = split(/\s+/, $line);
my $key = shift #key_vals;
if(exists $keys_i_need{$key}) {
INFO("key is $key value is " . join(", ", #key_vals));
push (#{$keys_i_need{$key}}, \#key_vals);
DEBUG(Dumper \%keys_i_need);
}
}
}
If I understand this correctly, it's a hash, where each value is an array reference with array references inside the array reference. I don't want to use Dumper because I want to pick out each piece.
I'm trying to read out what's been pulled into the hash but I'm getting an error message that says:
"my" variable $values masks earlier declaration in same statement at /home/rabdelaz/workspace/akatest_5/scripts/Viper/Stragglers.pl line 67.
foreach my $key (keys %$config_options) {
foreach my $arr_ref_of_arr_values (%$config_options{$key}) {
foreach my $values (#$arr_ref_of_arr_values) { #<----------line 67
foreach my $value (#$values) {
INFO("key $key has values $value");
}
}
}
}
This looks right to me. I can't quite figure out what perl is complaining about. Any thoughts?
I see what I did now.
I was confused (once again) by the fact that an array reference is a scalar and not an array. Although, as you can see from my original code I went the wrong direction any way (outside to the hash, rather than inside to the array ref. So my final code should look more like this:
foreach my $key (keys %$config_options) {
foreach my $arr_ref_of_arr_values ($$config_options{$key}) {
foreach my $values (#$arr_ref_of_arr_values) { #<----------line 67
foreach my $value (#$values) {
INFO("key $key has values $value");
}
}
}
}
In the course of debugging, I ended up with this to get the first value of the first array in the first key:
INFO("first value of first array of first key: " . ${${$$config_options{'A'}}[0]}[0]);
I then used this as my guidepost.
I am trying to count how many time DE10 and each of the keys in my ICD10 hash occurs in the same line in my file2.tsv. I further have to divide it by male/female (M/K).
I therefore made a hash called results. Each of the keys in this is named after the key in the ICD10 hash, and they refers to an array of 2 elements, the first counting the male, the second counting the females.
But I get this warning:
Can't use string ("0") as an ARRAY ref while "strict refs"
due to this line:
$results{$key}[1] +=1;
I am a little weak on this reference part, can someone help me with my mistake? thanks a lot
#!/usr/bin/perl -w
use strict;
###################
# loading my hash #
###################
my %icd10;
open(IN, '<', 'myfile.tsv') or die;
while (defined (my $line = <IN>)) {
chomp $line;
$icd10{$line} = 1;
}
close IN;
################
### COUNTING
#################
my %results;
open(IN, '<', 'myfile2.tsv') or die;
while (defined (my $line = <IN>)) {
chomp $line;
my #line = split('\t', $line);
my %hash;
for (my $i = 2; $i < scalar(#line); $i++){
$hash{$line[$i]} = 1;
}
if (grep (m/^DE10/, keys %hash)) {
foreach my $key (keys %icd10){
if (grep (m/^$key/, keys %hash)) {
if (exists $results{$key}) {
if ($line[1] eq 'M') {
$results{$key}[1] +=1;
}
elsif ($line[1] eq 'K'){
$results{$key}[2] +=1;
}
}
else{
if ($line[1] eq 'M') {
$results{$key}=(1,0);
}
elsif ($line[1] eq 'K'){
$results{$key}=(0,1);
}
}
If you want $results{$key} to be a reference to an array, then the parentheses in these two identical sentences $results{$key}=(1,0); should be square brackets, like this: $results{$key}=[1,0];.
To create a reference to an array, you can use backslash operator:
$arrayref = \#array;
To create a reference to an anonymous array you should use square brackets:
$arrayref = [ 'ele1', 'ele2' ];
See perlref for further details.
Given an array #A we want to check if the element $B is in it. One way is to say this:
Foreach $element (#A){
if($element eq $B){
print "$B is in array A";
}
}
However when it gets to Perl, I am thinking always about the most elegant way. And this is what I am thinking:
Is there a way to find out if array A contains B if we convert A to a variable string and use
index(#A,$B)=>0
Is that possible?
There are many ways to find out whether the element is present in the array or not:
Using foreach
foreach my $element (#a) {
if($element eq $b) {
# do something
last;
}
}
Using Grep:
my $found = grep { $_ eq $b } #a;
Using List::Util module
use List::Util qw(first);
my $found = first { $_ eq $b } #a;
Using Hash initialised by a Slice
my %check;
#check{#a} = ();
my $found = exists $check{$b};
Using Hash initialised by map
my %check = map { $_ => 1 } #a;
my $found = $check{$b};
use 5.10.1;
$B ~~ #A and say '$B in #A';
use List::AllUtils qw/ any /;
print "\#A contains $B" if any { $B eq $_ } #A;