Perl: Searching for item in an Array - arrays

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;

Related

Remove values in an array

This is our array :
my #array = ('?C=N;O=D',
'?C=M;O=A',
'?C=S;O=A',
'?C=D;O=A',
'/lab/blog/wp-content/',
'1-list.txt',
'2014/',
'2015/',
'rbxslider/',
'slideshow-gallery/',
'uigen_2015/'
);
how to remove all values before </lab/blog/wp-content/> value
shift #list until (shift (#list)=~m/wp-contnet/);
i have tried with this way but no result
Another way:
#array = grep /wp-content/../(?!)/, #array;
Close.
shift #array until $array[0] =~ /wp-content/;
Or if there's a chance that there might not be anything to remove,
while ($array[0] !~ /wp-content/) { shift #array; }
You might want to make sure you don't loop forever.
while (#array && $array[0] !~ /wp-content/) { shift #array; }
my $count = 0;
my #keep;
foreach (#array){
$count++ if m|/lab/blog/wp-content/|;
push #keep, $_ if $count > 0;
}
say foreach #keep;
/lab/blog/wp-content/
1-list.txt
2014/
2015/
rbxslider/
slideshow-gallery/
uigen_2015/
You're close, when you use the proper array name and correct the typo in "wp-content", but that doesn't include the 'wp-content' element which appears as though you'd like to do. The following checks the first element before shifting, instead of shifting it off and then checking it:
if (grep /wp-content/, #array){
shift #array until $array[0] =~ /wp-content/;
}
print "$_\n" for #array;
Output:
/lab/blog/wp-content/
1-list.txt
2014/
2015/
rbxslider/
slideshow-gallery/
uigen_2015/

Iterate through an array in Perl

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.../;
}

Perl - Apply grep to AoA and get particular element from already returned array

I have 2D array and I want to filter by specific index but return another index. I have tried this:
print (grep {$_->[0] eq "defuser"} #passwd_file_AoA)[2];
But gives me syntax error.
EDIT:
From this array
#AoA = ([1,"a","b"],[2,"c","d"]);
I want to get
"a"
I have tried following based on bellow suggestions but returns me 1
use Data::Dumper;
#AoA = ([1,"a","b"],[2,"c","d"]);
$a = map { $_->[1] } grep { $_->[0] == 1 } #AoA;
print Dumper $a
If you want to create a brand new array with the values from your array of arrays, you can use map and grep:
my #new_arr = map { $_->[2] } grep { $_->[0] eq "defuser" } #AoA;
If you want to print AND make a new array:
my #new_arr = map { say $_->[2]; $_->[2] } grep { $_->[0] eq "defuser" } #AoA;
(uses say, which requires perl 5.10 or greater and use feature ':5.10', but saves you having to type out \n every time you print to STDERR)
As ThisSuitIsBlackNot says, printing can be done with
for my $a (#AoA) {
say $_->[2] if $_->[0] eq 'defuser';
}

How can I loop over an array from the first occurrence of an element with a specific value using perl?

I have an array like ("valueA", "valueB", "valueC", "valueD") etc. I want to loop over the values of the array starting from (for example) the first instance of "valueC". Everything in the array before the first instance of the value "valueC" should be ignored; so in this case only "valueC" and "valueD" would be handled by the loop.
I can just put a conditional inside my loop, but is there a neater way to express the idea using perl?
my $seen;
for ( grep $seen ||= ($_ eq "valueC"), #array ) {
...
}
I think you also need to check if the "valueC" exist inside the array.
Hope this helps.
use strict;
use warnings;
use List::Util qw(first);
my #array = qw(valueA valueB valueC valueD);
my $starting_element = 'valueC';
# make sure that the starting element exist inside the array
# first search for the first occurrence of the $stating_element
# dies if not found
my $starting_index = first { $array[$_] eq $starting_element } 0 .. $#array
or die "element \"$starting_element\" does not exist inside the array";
# your loop
for my $index ($starting_index .. $#array) {
print $array[$index]."\n";
}
my $seen;
for ( #array ) {
$seen++ if /valueC/;
next unless $seen;
...
}
But that $seen is a little ungainly. The flip-flop operator looks tidier IMO:
for ( #array ) {
next unless /^valueC$/ .. /\0/;
# or /^valueC$/ .. '' !~ /^$;
# or $_ eq 'valueC' .. /\0/;
...
}
Or simply (building on ikegami's suggestion):
for ( grep { /^valueC$/ .. /(*FAIL)/ } #array ) { ... }
use List::MoreUtils qw( first_index );
foreach my $item ( #array[ ( first_index { $_ eq 'ValueC' } #array ) .. $#array ] ){
# process $item
}
my $start = 0;
++$start while $start < #array && $array[$start] ne 'valueC';
followed by either
for (#array[$start..$#array]) {
say;
}
or
for my $i ($start..$#array) {
say $array[$i];
}
TIMTOWTDI, but I think that:
foreach my $item (#list) {
next if !$seen && ($item ne 'valueC');
$seen++;
...
}
is both readable, correct and and terse enough. All the /valueC/ solution will process anything after "DooDadvalueCFuBAr", not what the OP asked. And, no you need no flipflop/range operator, and checking for the existence beforehand is really strange, besides requiring a possibly noncore package to perform a rather trivial task.The grep solution is really making my head spin, besides creating and tossing a temp array as a side effect.
If you want to get fancy and avoid ''ifs':
foreach my $item (#list) {
$seen || ($item eq 'valueC') || next;
$seen++;
...
}
Just don't write home about it. :-)

Perl splitting array based on condition using grep

I have some perl code that looks something like this:
my #array = map { rand } ( 1..100 );
my #matching = grep { $_ == $condition } #array;
#array = grep { $_ != $condition } #array;
This works ok, but what I would like to do is split the original array into two based on a single operation...I think I'm carrying out twice as many operations as strictly necessary.
Help appreciated!! Thanks.
This is where part from List::MoreUtils comes in handy.
use List::MoreUtils qw'part';
my($even,$odd) = part { $_ % 2 } #array;
This works great if you want each element of input in exactly one array of the output.
If you want to possibly put them in more than one of the arrays, you have to loop over them yourself.
The best way to do that is with a foreach loop.
my(#div2,#div3);
for my $elem (#array){
push #div2, $elem unless $elem % 2;
push #div3, $elem unless $elem % 3;
}
If there are a lot of similar checks you have to do, perhaps you should loop on what your testing against as-well.
my %div;
for my $elem (#array){
for my $div (2,3,5,7,11,13){
push #{ $out{$div} }, $elem unless $elem % $div;
}
}
By far the easiest method is to iterate your array and push values to either of the two arrays depending on the condition, as in the below example.
for (#array) {
if ($_ % 2) {push #odd, $_}
else {push #even, $_}
}
If you'd like to modify the source array:
for (my $i =0; $i < #array; ++$i) {
if ($array[$i] % 2) {
push #odd, splice (#array, $i--, 1);
}
}
Why didn't you recommend List::MoreUtils::part?
The module in question might not exists on the target system, which is always an annoying thing.
Also on the system I ran tests on I found that List::MoreUtils::part was twice as slow as first snippet in this post, though with different implementations of part it might be the opposite actually.
I love the simplicity of List::MoreUtils' part function:
sub part (&#) {
my ($code, #list) = #_;
my #parts;
push #{ $parts[ $code->($_) ] }, $_ foreach #list;
return #parts;
}
The resulting #parts array is an array of arrayrefs. #$parts[0] is the array of elements that returned false. #$parts[1] returned true.

Resources