Red_Dragon has asked for the wisdom of the Perl Monks concerning the following question:

Oh Fonts of Knowledge,

I am trying to populate a variable($tkt_data) to create a string that is structured as below:

"2", "submitted by", "7", "Status", "8", "a short, concise description +", "536870915", "Jobfail", "536870922", "finance", "536870926", "Stev +ens"
The data pair should only be included in the string if the variable contains a value and a comma should be appended at the end of each pair only if another pair is to be appended.

The data and variables are layed out as follows:

..........................# VALUE CONTAINED IN THE VARIABLE "2", "$p_suby", # submitted by "7", "$p_stat", # Status "8", "$p_desc", # a short concise description "536870915", "$p_catg", # Jobfail "536870922", "$p_agrp", # finance "536870926", "$p_lnam" # Stevens
Things I've tried that failed:
$counter = 0 ; if ($p_suby != "") {$tkt_data = "\"2\", \"$p_suby\"" ; $counter = $counter + 1 ;} if ($p_stat != "") {if ($counter > 0) {$tkt_data = "$tkt_data, \"7\", \"$p_stat\""} else {$tkt_data = "\"7\", \"$p_stat\""} $counter = $counter + 1 ;} if ($p_desc != "") {if ($counter > 0) {$tkt_data = "$tkt_data, \"8\", \"$p_desc\""} else {$tkt_data = "\"8\", \"$p_desc\""} $counter = $counter + 1 ;} if ($p_catg != "") {if ($counter > 0) {$tkt_data = "$tkt_data, \"536870915\", \"$p_catg +\""} else {$tkt_data = "\"536870915\", \"$p_catg\""} $counter = $counter + 1 ;} if ($p_agrp != "") {if ($counter > 0) {$tkt_data = "$tkt_data, \"536870922\", \"$p_agrp +\""} else {$tkt_data = "\"536870922\", \"$p_agrp\""} $counter = $counter + 1 ;} if ($p_lnam != "") {if ($counter > 0) {$tkt_data = "$tkt_data, \"536870926\", \"$p_lnam +\""} else {$tkt_data = "\"536870926\", \"$p_lnam\""} $counter = $counter + 1 ;}

Replies are listed 'Best First'.
Re: My Novice is Showing
by Roy Johnson (Monsignor) on Nov 18, 2003 at 19:38 UTC
    What you're doing seems very odd. Perhaps you should have a slightly more complex data structure to associate those magic numbers with the variables they correspond with.

    One major thing you're doing wrong is using numeric comparisons (!=) when you should be doing string comparisons (ne). You are also overwriting $tkt_data instead of appending to it.

    This is untested, but might do what you want. Season to taste.

    my @ar = ( ['2', $p_suby], ['7', $p_stat], ['8', $p_desc], ['536870915', $p_catg], ['536870922', $p_agrp], ['536870926', $p_lnam] ); my $tkt_data = ''; for (@ar) { if ($_->[1] ne '') { $tkt_data .= ',' if $tkt_data ne ''; $tkt_data .= sprintf('"%s%", "%s"', @$_); } }
    Alternatively,
    my $tkt_data = join ',' => map(sprintf('"%s%", "%s"', @$_) => grep($_->[1] ne '', @ar));
Re: My Novice is Showing
by blokhead (Monsignor) on Nov 18, 2003 at 19:37 UTC
    a comma should be appended at the end of each pair only if another pair is to be appended.
    Sounds like a job for join. Build an array/list of all your "12345", "$p_xxxx" strings and join them with ", ".

    As for the other restrictions, notice that you've had to hardcode every variable separately because they all have different ID numbers. If you were to group all the related $p_xxxx variables into one hash, and build a hash that maps record fields to ID numbers, your life could be a lot simpler:

    my %id_map; my @fields = qw/suby stat desc catg agrp lnam/; @id_map{@fields} = qw/2 7 8 536870915 536870922 536870926/; ######### my %p_record = ( suby => "foo", stat => "bar", desc => "baz", catg => "", agrp => "boo", lnam => "" ); my $tkt_data = join ", " => map { qq["$id_map{$_}", "$p_record{$_}"] } grep { length $p_record{$_} } @fields; print "$tkt_data\n"; # "2", "foo", "7", "bar", "8", "baz", "536870922" +, "boo"
    Now there are no individual cases, no plethora of if-statements, because all fields can now be handled the same way. Their ID number is fetched from the %id_map hash.

    blokhead

Re: My Novice is Showing
by duff (Parson) on Nov 18, 2003 at 19:35 UTC

    Why not use a hash instead of those icky scalars? Make life simpler:

    my %titles = ( 'suby' => 'submitted by', 'stat' => 'Status', 'desc' => 'a short concise description', 'catg' => 'Jobfail', 'agrp' => 'finance', 'lnam' => 'Stevens', ); # You'll likely want an array of these, but that's another post :-) my %data = ( 'suby' => 2, 'stat' => 7, 'desc' => 8, 'catg' => 536870915, 'agrp' => 536870922, 'lnam' => 536870926, ); my @fields = qw(suby stat desc catg agrp lnam); $tkt_data = join ',', map { $data{$_}, $titles{$_} } grep { defined ($data{$_}) } @fields;

    This is just off the top of my head so there are probably all sorts of typos and what not. The last line grabs only those keys of the hash that have defined values, then maps that to a list of two elements: the data value and its corresponding title. Then it's all joined with commas.

Re: My Novice is Showing
by cleverett (Friar) on Nov 18, 2003 at 19:40 UTC
    my @desc = ("submitted by", "status", "a short concise description", "Jobfail", "finance", "Stevens"); sub populate { my (@variables) = @_; return join(", ", map { qq/"$_"/ } map { $variables[$_]||'' ? ($variables[$_], $desc[$_]) : () } (0 .. $#desc)); } populate(2, 7, 8, 536870915, 536870922, 536870926);
    update: got rid of unneeded variables with a map.