Is there an easy way to print out a Perl array with commas in between each element?
Writing a for loop to do it is pretty easy but not quite elegant....if that makes sense.
Just use join():
# assuming #array is your array:
print join(", ", #array);
You can use Data::Dump:
use Data::Dump qw(dump);
my #a = (1, [2, 3], {4 => 5});
dump(#a);
Produces:
"(1, [2, 3], { 4 => 5 })"
If you're coding for the kind of clarity that would be understood by someone who is just starting out with Perl, the traditional this construct says what it means, with a high degree of clarity and legibility:
$string = join ', ', #array;
print "$string\n";
This construct is documented in perldoc -fjoin.
However, I've always liked how simple $, makes it. The special variable $" is for interpolation, and the special variable $, is for lists. Combine either one with dynamic scope-constraining 'local' to avoid having ripple effects throughout the script:
use 5.012_002;
use strict;
use warnings;
my #array = qw/ 1 2 3 4 5 /;
{
local $" = ', ';
print "#array\n"; # Interpolation.
}
OR with $,:
use feature q(say);
use strict;
use warnings;
my #array = qw/ 1 2 3 4 5 /;
{
local $, = ', ';
say #array; # List
}
The special variables $, and $" are documented in perlvar. The local keyword, and how it can be used to constrain the effects of altering a global punctuation variable's value is probably best described in perlsub.
Enjoy!
Also, you may want to try Data::Dumper. Example:
use Data::Dumper;
# simple procedural interface
print Dumper($foo, $bar);
For inspection/debugging check the Data::Printer module. It is meant to do one thing and one thing only:
display Perl variables and objects on screen, properly formatted (to
be inspected by a human)
Example usage:
use Data::Printer;
p #array; # no need to pass references
The code above might output something like this (with colors!):
[
[0] "a",
[1] "b",
[2] undef,
[3] "c",
]
You can simply print it.
#a = qw(abc def hij);
print "#a";
You will got:
abc def hij
# better than Dumper --you're ready for the WWW....
use JSON::XS;
print encode_json \#some_array
Using Data::Dumper :
use strict;
use Data::Dumper;
my $GRANTstr = 'SELECT, INSERT, UPDATE, DELETE, LOCK TABLES, EXECUTE, TRIGGER';
$GRANTstr =~ s/, /,/g;
my #GRANTs = split /,/ , $GRANTstr;
print Dumper(#GRANTs) . "===\n\n";
print Dumper(\#GRANTs) . "===\n\n";
print Data::Dumper->Dump([\#GRANTs], [qw(GRANTs)]);
Generates three different output styles:
$VAR1 = 'SELECT';
$VAR2 = 'INSERT';
$VAR3 = 'UPDATE';
$VAR4 = 'DELETE';
$VAR5 = 'LOCK TABLES';
$VAR6 = 'EXECUTE';
$VAR7 = 'TRIGGER';
===
$VAR1 = [
'SELECT',
'INSERT',
'UPDATE',
'DELETE',
'LOCK TABLES',
'EXECUTE',
'TRIGGER'
];
===
$GRANTs = [
'SELECT',
'INSERT',
'UPDATE',
'DELETE',
'LOCK TABLES',
'EXECUTE',
'TRIGGER'
];
This might not be what you're looking for, but here's something I did for an assignment:
$" = ", ";
print "#ArrayName\n";
Map can also be used, but sometimes hard to read when you have lots of things going on.
map{ print "element $_\n" } #array;
I've not tried to run below, though. I think this's a tricky way.
map{print $_;} #array;
Related
I would like to generate every possible consecutive substring of a string, including the end of the word/beginning from the word (cyclic) letter combinations. I've found an example in Python, but the only language I know is perl (and barely, I'm a beginner). I would appreciate it a lot if someone can help me translating the code to perl or to help me find a solution in perl.
the code is the following:
aa='ABCD'
F=[]
B=[]
for j in range(1,len(aa)+1,1):
for i in range(0,len(aa),1):
A=str.split(((aa*j)[i:i+j]))
B=B+A
C=(B[0:len(aa)*len(aa)-len(aa)+1])
it gives you:
C=['A', 'B', 'C', 'D', 'AB', 'BC', 'CD', 'DA', 'ABC', 'BCD', 'CDA', 'DAB', 'ABCD']`
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my $string = 'ABCD';
my #substrings;
for my $length (1 .. length $string) {
for my $pos (0 .. length($string) - 1) {
push #substrings, substr $string x 2, $pos, $length;
}
}
say for #substrings;
If you're interested in using a pre-built solution, you could checkout the CPAN, where I found the module String::Substrings. Because you want "wrap-around" substrings and want to eliminate the "substrings" that have the same length as the actual string, you'll have to do a little manipulation:
#!/usr/bin/perl
use strict;
use warnings;
use String::Substrings;
use feature 'say';
my $string = 'ABCD';
my %substrs;
for my $len (1..length($string)-1) {
$substrs{$_}++ for substrings("$string"x2, $len);
}
say for sort keys %substrs;
Results:
A
AB
ABC
B
BC
BCD
C
CD
CDA
D
DA
DAB
I have this 3 lines of code in a sub and I'm trying to write them together on one line only.. but I'm quite lost
my %p = #_;
my $arr = $p{name};
my #a = #$arr;
what's the correct way of doing this?
thank you!
my %p = #_;
#_ is assumed to contain key-value pairs which are then used to construct the hash %p.
my $arr = $p{name};
The argument list is assumed to have contained something along the lines of name, [1, 2, 3,] so that $p{name} is an reference to an array.
my #a = #$arr;
Dereference that array reference to get the array #.
Here is an invocation that might work with this prelude in a sub:
func(this => 'that', name => [1, 2, 3]);
If you want to reduce the whole prelude to a single statement, you can use:
my #a = #{ { #_ }->{name} };
as in:
#!/usr/bin/env perl
use strict;
use warnings;
use YAML::XS;
func(this => 'that', name => [1, 2, 3]);
sub func {
my #a = #{ { #_ }->{name} };
print Dump \#a;
}
Output:
---
- 1
- 2
- 3
If the array pointed to by name is large, and if you do not need a shallow copy, however, it may be better to just stick with references:
my $aref = { #_ }->{ name };
OK so what you're doing is:
Assign a list of elements passed to the sub, to a hash.
extract a value from that hash (that appears to be an array reference)
dereference that into a standalone array.
Now, I'm going to have to make some guesses as to what you're putting in:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
sub test {
my %p = #_;
my $arr = $p{name};
my #a = #$arr;
print Dumper \#a;
}
my %input = ( fish => [ "value", "another value" ],
name => [ "more", "less" ], );
test ( %input );
So with that in mind:
sub test {
print join "\n", #{{#_}->{name}},"\n";
}
But actually, I'd suggest what you probably want to do is pass in the hashref in the first place:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
sub test {
my ( $input_hashref ) = #_;
print Dumper \#{$input_hashref -> {name}};
}
my %input = ( fish => [ "value", "another value" ],
name => [ "more", "less" ], );
test ( \%input );
Also:
Don't use single letter variable names. It's bad style.
that goes double for a and b because $a and $b are for sorting. (And using #a is confusing as a result).
What is the smartest way of searching through an array of strings for a matching string in Perl?
One caveat, I would like the search to be case-insensitive
so "aAa" would be in ("aaa","bbb")
It depends on what you want the search to do:
if you want to find all matches, use the built-in grep:
my #matches = grep { /pattern/ } #list_of_strings;
if you want to find the first match, use first in List::Util:
use List::Util 'first';
my $match = first { /pattern/ } #list_of_strings;
if you want to find the count of all matches, use true in List::MoreUtils:
use List::MoreUtils 'true';
my $count = true { /pattern/ } #list_of_strings;
if you want to know the index of the first match, use first_index in List::MoreUtils:
use List::MoreUtils 'first_index';
my $index = first_index { /pattern/ } #list_of_strings;
if you want to simply know if there was a match, but you don't care which element it was or its value, use any in List::Util:
use List::Util 1.33 'any';
my $match_found = any { /pattern/ } #list_of_strings;
All these examples do similar things at their core, but their implementations have been heavily optimized to be fast, and will be faster than any pure-perl implementation that you might write yourself with grep, map or a for loop.
Note that the algorithm for doing the looping is a separate issue than performing the individual matches. To match a string case-insensitively, you can simply use the i flag in the pattern: /pattern/i. You should definitely read through perldoc perlre if you have not previously done so.
I guess
#foo = ("aAa", "bbb");
#bar = grep(/^aaa/i, #foo);
print join ",",#bar;
would do the trick.
Perl 5.10+ contains the 'smart-match' operator ~~, which returns true if a certain element is contained in an array or hash, and false if it doesn't (see perlfaq4):
The nice thing is that it also supports regexes, meaning that your case-insensitive requirement can easily be taken care of:
use strict;
use warnings;
use 5.010;
my #array = qw/aaa bbb/;
my $wanted = 'aAa';
say "'$wanted' matches!" if /$wanted/i ~~ #array; # Prints "'aAa' matches!"
If you will be doing many searches of the array, AND matching always is defined as string equivalence, then you can normalize your data and use a hash.
my #strings = qw( aAa Bbb cCC DDD eee );
my %string_lut;
# Init via slice:
#string_lut{ map uc, #strings } = ();
# or use a for loop:
# for my $string ( #strings ) {
# $string_lut{ uc($string) } = undef;
# }
#Look for a string:
my $search = 'AAa';
print "'$string' ",
( exists $string_lut{ uc $string ? "IS" : "is NOT" ),
" in the array\n";
Let me emphasize that doing a hash lookup is good if you are planning on doing many lookups on the array. Also, it will only work if matching means that $foo eq $bar, or other requirements that can be met through normalization (like case insensitivity).
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my #bar = qw(aaa bbb);
my #foo = grep {/aAa/i} #bar;
print Dumper \#foo;
Perl string match can also be used for a simple yes/no.
my #foo=("hello", "world", "foo", "bar");
if ("#foo" =~ /\bhello\b/){
print "found";
}
else{
print "not found";
}
For just a boolean match result or for a count of occurrences, you could use:
use 5.014; use strict; use warnings;
my #foo=('hello', 'world', 'foo', 'bar', 'hello world', 'HeLlo');
my $patterns=join(',',#foo);
for my $str (qw(quux world hello hEllO)) {
my $count=map {m/^$str$/i} #foo;
if ($count) {
print "I found '$str' $count time(s) in '$patterns'\n";
} else {
print "I could not find '$str' in the pattern list\n"
};
}
Output:
I could not find 'quux' in the pattern list
I found 'world' 1 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
I found 'hello' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
I found 'hEllO' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
Does not require to use a module.
Of course it's less "expandable" and versatile as some code above.
I use this for interactive user answers to match against a predefined set of case unsensitive answers.
I keep printing my hash as # of buckets / # allocated.
How do I print the contents of my hash?
Without using a while loop would be most preferable (for example, a one-liner would be best).
Data::Dumper is your friend.
use Data::Dumper;
my %hash = ('abc' => 123, 'def' => [4,5,6]);
print Dumper(\%hash);
will output
$VAR1 = {
'def' => [
4,
5,
6
],
'abc' => 123
};
Easy:
print "$_ $h{$_}\n" for (keys %h);
Elegant, but actually 30% slower (!):
while (my ($k,$v)=each %h){print "$k $v\n"}
Here how you can print without using Data::Dumper
print "#{[%hash]}";
For debugging purposes I will often use YAML.
use strict;
use warnings;
use YAML;
my %variable = ('abc' => 123, 'def' => [4,5,6]);
print "# %variable\n", Dump \%variable;
Results in:
# %variable
---
abc: 123
def:
- 4
- 5
- 6
Other times I will use Data::Dump. You don't need to set as many variables to get it to output it in a nice format than you do for Data::Dumper.
use Data::Dump = 'dump';
print dump(\%variable), "\n";
{ abc => 123, def => [4, 5, 6] }
More recently I have been using Data::Printer for debugging.
use Data::Printer;
p %variable;
{
abc 123,
def [
[0] 4,
[1] 5,
[2] 6
]
}
( Result can be much more colorful on a terminal )
Unlike the other examples I have shown here, this one is designed explicitly to be for display purposes only. Which shows up more easily if you dump out the structure of a tied variable or that of an object.
use strict;
use warnings;
use MTie::Hash;
use Data::Printer;
my $h = tie my %h, "Tie::StdHash";
#h{'a'..'d'}='A'..'D';
p %h;
print "\n";
p $h;
{
a "A",
b "B",
c "C",
d "D"
} (tied to Tie::StdHash)
Tie::StdHash {
public methods (9) : CLEAR, DELETE, EXISTS, FETCH, FIRSTKEY, NEXTKEY, SCALAR, STORE, TIEHASH
private methods (0)
internals: {
a "A",
b "B",
c "C",
d "D"
}
}
The answer depends on what is in your hash. If you have a simple hash a simple
print map { "$_ $h{$_}\n" } keys %h;
or
print "$_ $h{$_}\n" for keys %h;
will do, but if you have a hash that is populated with references you will something that can walk those references and produce a sensible output. This walking of the references is normally called serialization. There are many modules that implement different styles, some of the more popular ones are:
Data::Dumper
Data::Dump::Streamer
YAML::XS
JSON::XS
XML::Dumper
Due to the fact that Data::Dumper is part of the core Perl library, it is probably the most popular; however, some of the other modules have very good things to offer.
My favorite: Smart::Comments
use Smart::Comments;
# ...
### %hash
That's it.
Looping:
foreach(keys %my_hash) { print "$_ / $my_hash{$_}\n"; }
Functional
map {print "$_ / $my_hash{$_}\n"; } keys %my_hash;
But for sheer elegance, I'd have to choose wrang-wrang's. For my own code, I'd choose my foreach. Or tetro's Dumper use.
I really like to sort the keys in one liner code:
print "$_ => $my_hash{$_}\n" for (sort keys %my_hash);
If you want to be pedantic and keep it to one line (without use statements and shebang), then I'll sort of piggy back off of tetromino's answer and suggest:
print Dumper( { 'abc' => 123, 'def' => [4,5,6] } );
Not doing anything special other than using the anonymous hash to skip the temp variable ;)
The easiest way in my experiences is to just use Dumpvalue.
use Dumpvalue;
...
my %hash = { key => "value", foo => "bar" };
my $dumper = new DumpValue();
$dumper->dumpValue(\%hash);
Works like a charm and you don't have to worry about formatting the hash, as it outputs it like the Perl debugger does (great for debugging). Plus, Dumpvalue is included with the stock set of Perl modules, so you don't have to mess with CPAN if you're behind some kind of draconian proxy (like I am at work).
I append one space for every element of the hash to see it well:
print map {$_ . " "} %h, "\n";
I am new to programming and hence I am stuck on a basic level problem.
Following is code I wrote for comparison. But the result I get does not make sense to me. I would appreciate if someone could tell me what is going wrong.
There are two arrays: #array1 , #array2 of unequal length.
I wish to compare both and list down values not present in #array1.
my %temp = map {$_,$_}#array2;
for (#array1){
next if exists $temp{$_};
open (FILE, ">>/filename") or die "$!";
print FILE "$_\n";
close(FILE);
}
See the FAQ How do I compute the difference of two arrays? How do I compute the intersection of two arrays?
Adapting the code you posted:
#!/usr/bin/perl
use strict; use warnings;
my #x = 1 .. 10;
my #y = grep { $_ % 2 } #x;
my %lookup = map { $_ => undef } #y;
for my $x ( #x ) {
next if exists $lookup{$x};
print "$x\n";
}
If you're doing this for a test, which I assume you are I would highly suggest is_deeply in the newer versions of Test::More
You'll have to update Test::More
cpanp install Test::More
or if you're on perl 5.5
cpan Test::More
Then you'll have use it
use Test::More;
tests => 1
is_deeply ( \#arr1, \#arr2, 'test failed' );
If you're not doing this for testing, but you're doing this for introspective purposes and the arrays are small, I'd suggest using XXX:
cpanp install http://search.cpan.org/CPAN/authors/id/I/IN/INGY/XXX-0.12.tar.gz
Then you'll have use it
use XXX;
YYY [ \#arr1, \#arr2 ];
That's some pretty clever code you've got there. Your code is more or less identical to what the Perl FAQ says. I might be tempted to do this, however:
my %tmp = map { $_ => 1 } #array2;
my #diff = grep { not exists $tmp{$_} } #array1;
This gets everything in #array1 that's not in #array2, but avoiding all of those out-of-style looping constructs (yay for functional programming). Though what I'd really do is this:
sub comp (\#\#) {
my %t = map { $_ => 1 } #{$_[1]};
return grep { not exists $t{$_} } #{$_[0]};
}
Then you can just do:
my #diff = comp(#array1, #array2); # get items in #array1 not in #array2
#diff = comp(#arraty2, #array1); # vice versa
Or you can go to CPAN. List::Compare::Functional::complement() does what you want, though the syntax is reversed.
Swap #array1 and #array2 in your code?
For simple values like strings or numbers, the following should work
my #result;
my $hosts = [qw(host1 host2 host3 host4 host5)];
my $stie_obj = [qw(host1 host5 host6)];
#result = map { my $a=$_; my $b=grep {/$a/} #$site_obj; $b==0 ? $a : () } #$hosts;
print Dumper (#result);
Should give :
$VAR1 = 'host2';
$VAR2 = 'host3';
$VAR3 = 'host4';