Re: How to split a string (an explanation of why you wanted an array)
by Ovid (Cardinal) on Jan 28, 2005 at 16:19 UTC
|
OK, so now you know that you can do what you want and tons of people have been thoughtful enough to tell you that you don't want to do that, but no one bothered to tell you why.
Generally, whenever you see variables whose names exhibit a consistent pattern such -- of which your $f1, $f2, $f3, etc. certainly qualifies -- it implies that these variables are logically grouped together. In your case, people suggested an array named @f. Another example would be variables like $customer_fname, $customer_lname, $customer_phone, etc. In this case, a hash would be a better choice:
%customer = (
fname => 'John',
lname => 'Doe',
phone => undef,
);
If the variables really don't belong together, there's a good chance that they have been poorly named and are likely to mislead programmers looking at your code (I wonder how many lone programmers get irritated when they hear people talk about others looking at their code?).
However, if those variables are logically grouped together, they should probably be grouped together in your code in a single construct, such as an array or hash. There are a variety of reasons for this, but two of the biggest are clean code and ease of use. For example, I routinely see stuff like this:
sub thing {
my $string = shift;
my ($f0, $f1, $f2, $f3, $f4, $f5) = split /|/, $string;
$f2 = $f4 + 5;
return ($f0, $f2, $f3);
}
Well, that's ugly. You're creating variables only to throw them away and it's not clear what you're doing. However, not only is this not clean code, it's also harder to work with. Let's say your boss wants to know why you're throwing away that second variable? So you add it:
sub thing {
my $string = shift;
my ($f0, $f1, $f2, $f3, $f4, $f5) = split /|/, $string;
$f2 = $f4 + 5;
return ($f0, $f1, $f2, $f3);
}
Now you have a problem. Everywhere where you call this code will now have the $f2, and $f3 variables shifted away by one and you'll have to go through and fix all of them. Had you put the variables in an array and returned that, you may return extra data you don't need now, but the code is clean and easier to use later.
sub thing {
my $string = shift;
my @f = split /|/, $string;
$f[2] = $f[4] + 5;
return @f;
}
There are still problems with that code (hard-coded constant and poorly named variables), but what happens if it turns out there is a $f6 and $f7 added later on? You may have to update some code to process it, but you might not have to update the sub to handle it because logically related variables were grouped together appropriately.
I hope I've shed a little light on that subject :)
| [reply] [d/l] [select] |
|
|
foreach ( $f0, $f1, $f2, $f3, $f4, $f5 ) {
# ...
}
but in other languages it takes an incredible amount of teeth gnashing to do something like that. And even so, it is annoying to write out every time, invites typos, invites copy-paste, and is annoying to read.
Makeshifts last the longest. | [reply] [d/l] |
Re: How to split a string
by Limbic~Region (Chancellor) on Jan 28, 2005 at 15:41 UTC
|
Red_Dragon,
Is there a way in Perl to...
The answer to this question is almost always yes and there is almost always more than one way to do it. "There is more than one way to do it" is one of Perl's mottos. In this case, I will provide a straight forward answer.
my $str = '1029576843';
my @f = split //, $str;
print $f[ 4 ]; # 5
Using a different variable for each piece of the string would require symbolic references which is typically frowned on which is why I used an array | [reply] [d/l] |
|
|
| [reply] |
Re: How to split a string
by ikegami (Patriarch) on Jan 28, 2005 at 15:41 UTC
|
Yes, but it's very bad practice, because it's just too easy to make errors, and it makes your code much less readable. You could use an array instead:
my @f = split(//, $s);
A alternate way to split the string:
my @f = $s =~ /./gs;
An example of how to manipulate the array:
print("\@f has ", scalar(@f), " elements:\n");
print("\$f[$_] = $f[$_]\n") for (0..$#f);
| [reply] [d/l] [select] |
Re: How to split a string
by merlyn (Sage) on Jan 28, 2005 at 15:41 UTC
|
my @f = split //, $s;
| [reply] [d/l] |
|
|
f_zero = 1;
f_one = 0;
f_two = 2;
f_three = 9;
*grin*
| [reply] [d/l] |
|
|
my @numword = qw( zero one two three four five six seven eight nine te
+n );
my $i = 0;
${ "f_" . $numword[ $i++ ] } = $_ for split //, $string;
Nevermind the fact that you can vandalize the symbol table to put things in it with whose names don't conform to identifier rules, such as ${ '[ ha ha ha ]' } = 1;.
Makeshifts last the longest. | [reply] [d/l] [select] |
|
|
|
|
|
|
$payload_32
$sensor_7
$sensor_125
$thermistor_10um_1
I won't use your tyrannical anti-numerical variable name future language. You'll have to educate people instead.
"Look, Shiny Things!" is not a better business strategy than compatibility and reuse.
| [reply] [d/l] |
|
|
| [reply] [d/l] |
|
|
|
|
|
Re: How to split a string
by hardburn (Abbot) on Jan 28, 2005 at 15:43 UTC
|
No looping required, thanks to the magic split //:
my (@f) = split // => $s;
I'd suggest having it in an array instead of individual scalars (it usually ends up being far easier to deal with in the rest of the code), but if you really want it that way:
my (
$f0,
$f1,
$f2,
$f3,
$f4,
$f5,
$f6,
$f7,
$f8,
$f9,
) = split // => $s;
"There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.
| [reply] [d/l] [select] |
Re: How to split a string
by kutsu (Priest) on Jan 28, 2005 at 15:51 UTC
|
Since several people have given the @f = split... answer: why do you want to split a string into each individual character anyway? I ask because there may be an easier way to do this.
If, for example, you only want the 4 character, my $f = substr($s, 4, 1) would work (and is proably easier then $fourthchar = $f[4];, after the split, if that's all you want).
"Cogito cogito ergo cogito sum - I think that I think, therefore I think that I am." Ambrose Bierce
| [reply] [d/l] [select] |
|
|
The purpose of splitting the string into serialized variables is to use the values in those variables as flags to control reporting granularity. If properly deployed in the Perl code will allow for adjustment of what is reported to a logfile without having to modify the Perl code. The only modification will be to the control string which is housed in an SQL table. Thank you for considering my question.
R_D
| [reply] |
|
|
my $str = '1029576843';
my @f = split //, $str;
for (@f)
{
#$_ is now 0; next run will be 1 and so on
print;
}
#or
for my $current_number (@f)
{
#$current_number is now 0; next run will be 1 and so on
print $current_number;
}
"Cogito cogito ergo cogito sum - I think that I think, therefore I think that I am." Ambrose Bierce
| [reply] [d/l] |
Re: How to split a string
by TedYoung (Deacon) on Jan 28, 2005 at 15:42 UTC
|
Well, generally, you may be better using an array. This can be done quite easily with:
@f = split //, $s;
# Now, each char is in $f[0], $f[1], etc.
If you absolutely must have seperated variables, you would have to venture into symbolic dereferencing <insert standard security warnings here>.
my $i = 0;
${'f' . $i ++} = $_ for split //, $s
This code is untested, but should work ;-)
Ted Young
($$<<$$=>$$<=>$$<=$$>>$$) always returns 1. :-)
| [reply] [d/l] [select] |
|
|
Thank you for generously considering my question and providing an elegant solution, I had already tried the array form as a solution, but it was inadequate for my purposes due to my limited understanding of Perl. The string in question is extracted from an SQL table. The values placed in serialized variables are used as flags that govern print statements. Properly deployed they will allow granular control over what is written to a logfile without having to alter Perl code. All adjustments can be made by changing the control string in the SQL table.
Thanks again, I truly appreciate your input.
R_D
| [reply] |
Re: How to split a string
by gellyfish (Monsignor) on Jan 28, 2005 at 15:44 UTC
|
If you want to put the values into an array then you could do @array = split //, $s; - named variables like you have are redolent of 'symbolic references' and widely disparaged ...
/J\
| [reply] [d/l] |
Re: How to split a string
by moot (Chaplain) on Jan 28, 2005 at 15:44 UTC
|
Yes, but a better approach might be to use an array:
my @array = split //, $s;
If you really must use separate variables, you could use the string form of eval, but this is generally considered bad style:
no strict 'vars';
for (split //, $s) { eval "\$f$i = $_"; ++$i }
Both approaches are quite brittle and rely on your string only having one digit per target variable. | [reply] [d/l] [select] |
|
|
my $i = 0;
for( split //, $s ) { no strict 'refs'; ${ 'f' . $i++ } = $_ }
Makeshifts last the longest. | [reply] [d/l] |