Is doing a lot more work than it should. You are actually splitting on empty strings (that's what .*? will always evaluate to) and storing the delimiters (the empty strings), so the string "foo" gets split as ("f", "", "o", "", "o"). If you want to split in individual characters, it's better to do:@q = split(/(.*?)/, $p);
which splits on an empty string, but without the regex, and does not store the delimiters, which you do not need anyway, and does not affect the subsequent code.@q = split(//,$p);
which also automatically assigns $_ for you on each iteration.foreach (@q) {
Restructuring the insides of the loop, we can get:@q = split (//, $p); foreach (@q) { $count++ if $_ eq $matchchar; if ($_ eq $matchchar && ($count >= $nummatch)) { $_ = $repchar; } } $out = join ("", @q); print "out === $out";
Now compressing the two if's, we get:foreach (@q) { if ($_ eq $matchchar) { if (++$count >= $nummatch) { $_ = $repchar; } } }
Now, notice that we are assigning one value to $_ when a certain condition is satisfied, and another (actually leaving its old value) when it's not. So we could use the conditional operator to eliminate the if altogether:foreach (@q) { if ($_ eq $matchchar && ++$count >= $nummatch) { $_ = $repchar; } }
And now, notice that we are using the foreach to compute a value based on each element of @q. Ideal use of map!foreach (@q) { $_ = ($_ eq $matchchar && ++$count >= $nummatch)?$repchar:$_; }
And now we don't need to initially asign the result of the split to @q, because all we are doing with it is passing it as argument to map, so we can do:@q = map { ($_ eq $matchchar && ++$count >= $nummatch)?$repchar:$_ } @q;
And finally, we can eliminate @q altogether because we can pass the result of the map directly to the join:@q = map { ($_ eq $matchchar && ++$count >= $nummatch)?$repchar:$_ } split(//, $p);
Proof that any program can be transformed to a one-liner in Perl :-)$out = join ("", map { ($_ eq $matchchar && ++$count >= $nummatch)?$repchar:$_ } split (//, $p));
Man that was fun :-)
--ZZamboni
In reply to Re: Re: Replacing a given character starting with the xth occurence in a string
by ZZamboni
in thread Replacing a given character starting with the xth occurence in a string
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |