I have an array of strings that I would like to use the join function on. However, I would like to prefix each string with the same string. Can I do this in one line as opposed to iterating through the array first and changing each value before using join?
Actually it's a lil bit trickier. The prefix is not part of the join separator. Meaning if you used a prefix like "num-" on an array of (1,2,3,4,5), you will want to get this result: num-1,num-2,num-3,num-4,num-5
This code:
my #tmp = qw(1 2 3 4 5);
my $prefix = 'num-';
print join "\n", map { $prefix . $_ } #tmp;
gives:
num-1
num-2
num-3
num-4
num-5
Just make the prefix part of the join:
my #array = qw(a b c d);
my $sep = ",";
my $prefix = "PREFIX-";
my $str = $prefix . join("$sep$prefix", #array);
You could also use map to do the prefixing if you prefer:
my $str = join($sep, map "$prefix$_", #array);
Related
Here is my code named reverse.pl
#!usr/bin/perl -w
use 5.016;
use strict;
while(my $line=<>)
{
my #array=();
push (#array,$line);
#array=reverse#array;
say #array;
}
Test file named a.txt
A B C D
E F G H
I J K L
M N O P
Q R S T
My command is perl reverse.pl a.txt
Why it can't implement the reverse function?
I want to show the result is:
D C B A
H G F E
and so on.
Reverse in a scalar context reverses a scalar.
Reverse in a list context reverses the list, but not each scalar within the list.
You explicitly turn your scalar $line into a list with one item and then reverse the order of the items.
Try this:
#!/usr/bin/perl
use 5.016;
use strict;
while (my $line=<>) {
chomp($line);
say scalar reverse $line;
}
If you have an array and want to reverse each element (but not the elements), use map:
my #array = qw(Alpha Beta Gamma);
#array = map { scalar reverse $_ } #array;
print "#array\n";
If you want to do both (reverse each element and the elements themselves), do:
#array = map { scalar reverse $_ } reverse #array;
or:
#array = reverse map { scalar reverse $_ } #array;
When you say:
push #array, $line;
You're creating an array of one value that's equal to the line.
$array[0] = "A B C D";
When you say:
#array = reverse #array;
You are reversing that single member array. The first element becomes the last, and the last element becomes the first, etc.. However, you only have one element, so there's nothing to reverse.
What you want to do is create an array with your line:
my #array = split /\s+/, $line;
This will create an array with each character being a separate element of the array. For example, your first line:
$array[0] = "A";
$array[1] = "B";
$array[2] = "C";
$array[3] = "D";
Now, if you use reverse on this array, you'll get:
$array[0] = "D";
$array[1] = "C";
$array[2] = "B";
$array[3] = "A";
Here's the program:
use strict;
use warnings;
use feature qw(say);
while ( my $line = <> ) {
chomp $line;
my #array = split /\s+/, $line;
say join " ", reverse $line;
}
The join function takes an array, and joins each element into a single line -- thus rebuilding your line.
By the way, I could have done this:
#array = reverse #array;
say "#array"; #Quotes are important!
This is because Perl will automatically join an array with whatever character is in $". This is a Perl variable that is used for joining arrays when that array is placed in quotation marks, and the default value is a single space.
Personally, I rather prefer the say join " ", reverse $line;. It's more obvious what is going on, and doesn't depend upon the value of rarely used variables.
I have an input variable, say $a. $a can be either number or string or mix of both.
My question is how can I strip off the variable to separate numeric digits and alphabetic characters?
Example;
$a can be 'AB9'
Here I should be able to store 'AB' in one variable and '9' in other.
How can I do that?
Check this version, it works with 1 or more numeric and alphabetic characters in a variable.
#!/usr/bin/perl
use strict;
use Data::Dumper;
my $var = '11a';
my (#digits, #alphabetics);
while ($var =~ /([a-zA-Z]+)/g) {
push #alphabetics, $1;
}
while ($var =~ /(\d+)/g) {
push #digits, $1;
}
print Dumper(\#alphabetics);
print Dumper(\#digits);
Here's one way to express it very shortly:
my ($digits) = $input =~ /(\d+)/;
my ($alpha) = $input =~ /([a-z]+)/i;
say 'digits: ' . ($digits // 'none');
say 'non-digits: ' . ($alpha // 'none');
It's important to use the match operator in list context here, otherwise it would return if the match succeeded.
If you want to get all occurrences in the input string, simply change the scalar variables in list context to proper arrays:
my #digits = $input =~ /(\d+)/g;
my #alpha = $input =~ /([a-z]+)/gi;
say 'digits: ' . join ', ' => #digits;
say 'non-digits: ' . join ', ' => #alpha;
For my $input = '42AB17C', the output is
digits: 42, 17
non-digits: AB, C
Below script break the sequence at every 'E' and subsequently an 'E' is added on to each fragment. But I'm not getting 'E' attached to my last element, Why?
use strict;
use warnings;
my $s = 'ABCDEABCDEABCDEABCDEABCDE';
my #a = split /E(?!P)/, $s;
my $result = join "E,", #a;
my #final = split /,/, $result;
print "#final\n";
A join joins its first argument between successive elements. If you want to add the final "E", you could simply do:
$s = 'ABCDEABCDEABCDEABCDEABCDE';
#a = split(/E(?!P)/, $s);
print join ("E ", #a), "E\n";
See the documentation of split:
By default, empty leading fields are preserved, and empty trailing ones are deleted.
I have a string str a\tb\tc\td\te
I want the 1st field value a to go in a variable, then 2nd field value b to go in other variable, then both c\td to go in 3rd variable and last field value e to go in one variable.
If I do
my ($a,$b,$c,$d) = split(/\t/,$_,4);
$c will acquire only c and $d will acquire d\te
I can do:
my ($a,$b,$c) = split(/\t/,$_,3);
Then c will get c\td\te
and I can somehow (How?) get rid of last value and get it in $d
How to achieve this?
split is good when you're keeping the order. If you're breaking the ordering like this you have a bit of a problem. You have two choices:
split according to \t and then join the ones you want.
be explicit.
an example of the first choice is:
my ($a,$b,$c1, $c2, $d) = split /\t/, $_;
my $c = "$c1\t$c2";
an example of the second choice is:
my ($a, $b, $c, $d) = (/(.*?)\t(.*?)\t(.*?\t.*?)\t(.*?)/;
each set of parentheses captures what you want exactly. Using the non-greedy modifier (?) after the * ensures that the parentheses won't capture \t.
Edit: if the intent is to have an arbitrary number of variables, you're best off using an array:
my #x = split /\t/, $_;
my $a = $x[0];
my $b = $x[1];
my $c = join "\t", #x[2..($#x-1)];
my $d = $x[-1];
You can use a regex with a negative look-ahead assertion, e.g.:
my #fields = split /\t(?!d)/, $string;
How do i reformulate a string in perl?
For example consider the string "Where is the Louvre located?"
How can i generate strings like the following:
"the is Louvre located"
"the Louvre is located"
"the Louvre located is"
These are being used as queries to do a web search.
I was trying to do something like this:
Get rid of punctuations and split the sentence into words.
my #words = split / /, $_[0];
I don't need the first word in the string, so getting rid of it.
shift(#words);
And then i need move the next word through out the array - not sure how to do this!!
Finally convert the array of words back to a string.
How can I generate all permutations of an array in Perl?
Then use join to glue each permutation array back together into a single string.
Somewhat more verbose example:
use strict;
use warnings;
use Data::Dumper;
my $str = "Where is the Louvre located?";
# split into words and remove the punctuation
my #words = map {s/\W+//; $_} split / /, $str;
# remove the first two words while storing the second
my $moving = splice #words, 0 ,2;
# generate the variations
my #variants;
foreach my $position (0 .. $#words) {
my #temp = #words;
splice #temp, $position, 0, $moving;
push #variants, \#temp;
}
print Dumper(\#variants);
my #head;
my ($x, #tail) = #words;
while (#tail) {
push #head, shift #tail;
print join " ", #head, $x, #tail;
};
Or you can just "bubble" $x through the array: $words[$n-1] and words[$n]
foreach $n (1..#words-1) {
($words[$n-1, $words[$n]) = ($words[$n], $words[$n-1]);
print join " ", #words, "\n";
};