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

Hello!

I have this:

my @data = [1,5,7,8,9,10,11,3,3,5,5,5,7,2,2];
as example, using it to give it to GD::Graph::histogram for plotting a histogram.
But now I have to plot several histograms and the data is coming each histogrammdata one line from a file.
E.g. my inputfile has as first line
1,5,7,8,9,10,11,3,3,5,5,5,7,2,2
But how I can read the line and assign it to @data?
I do this:
(@histofeld) = split(',',$input[$i]);
where @input contains line by line from my input. But it does not work, because it is taking the elements of @histofeld as a string.
How can I get it work?

Regards, buchi

Replies are listed 'Best First'.
Re: How to get data to an array?
by haukex (Archbishop) on Aug 31, 2017 at 17:14 UTC
    it does not work, because it is taking the elements of @histofeld as a string

    It is unclear to me what the relationship between your different variables @data, @histofeld and @input is. Could you please provide a short piece of code that we can run that demonstrates the problem, along with sample input and the expected output for that input? See Short, Self-Contained, Correct Example and How do I post a question effectively?

    At the moment I can only guess that you might be trying to build an "array of arrays", which is shown (with sample code) in perldsc.

    Since your data appears to be comma-separated, you should probably use the proper module for that, Text::CSV (also install Text::CSV_XS for speed):

    use warnings; use strict; use Text::CSV; my $csv = Text::CSV->new({ binary=>1, auto_diag=>2 }); open my $fh, '<', 'inputfilename' or die $!; my @data; while ( my $row = $csv->getline($fh) ) { push @data, $row; } $csv->eof or $csv->error_diag; close $fh; use Data::Dumper; print Dumper(\@data);
Re: How to get data to an array?
by flightdm (Acolyte) on Aug 31, 2017 at 19:28 UTC
    Unfortunately, what you've shown so far is not coherent information. E.g.,
    my @data = [1,5,7,8,9,10,11,3,3,5,5,5,7,2,2];
    isn't particularly useful since you're assigning a scalar list reference to an array (meaning that you'll always end up with a single-element array.) Something like this would make more sense:
    my $data = [1,5,7,8,9,10,11,3,3,5,5,5,7,2,2];
    I'm going to make some assumptions here about what you're trying to do; please feel free to correct any false ones. If you're trying to read a file that is composed of lines with comma-separated values, and where each line should be read in as a list reference of the above type, then something like this should be useful:
    use strict; open my $fh, '<', 'file' or die "file: $!\n"; my @data; while (<$fh>){ chomp; push @data, [split /,/]; }
    Each of the elements of @data will be a reference to a list containing the values on each line.

      Hello flightdm,

      You do not need to open the file handle and pass it to the diamond operator for reading. You can do it all in one, ref. I/O Operators. Read also eof for multiple files.

      Sample of code with output:

      Hope this helps, BR.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
        Hi -

        Thanks, but I'm quite familiar with the DATA filehandle, STDIN, and other methods of getting the data in. I'm not sure why you're bringing it up, since the scenario I stated -

        If you're trying to read a file that is composed of lines with comma-separated values

        - explicitly specifies an external file, as does the OP's request... and your addendum has no relation to the solution that was asked for (that is, getting data into an array.)

        Perhaps it'll add to someone's education, though.
Re: How to get data to an array?
by thanos1983 (Parson) on Sep 01, 2017 at 00:00 UTC

    Hello buchi2

    I seems there is a bit of confusion, on what you are asking and what you want to create at the end.

    Let's take it one step at a time. You want to open a file that contains data in CSV format. Fellow Monks haukex, flightdm and dbander have provided you with examples on how to do that.

    The reason is that you asked for (@histofeld) = split(',',$input[$i]); which is not what you need. From the documentation of the module GD::Graph::histogram/USAGE you can see $data = [1,5,7,8,9,10,11,3,3,5,5,5,7,2,2]; that the data need to populated in array reference format and not a simple array. Read more here on perldoc/Making-References.

    As a next step you wrote But now I have to plot several histograms and the data is coming each histogrammdata one line from a file. So I decided to take it a bit further and write a more generic script for you. What the script does, it takes an n number of files (CSV format) process them and create an Hash of Hashes of Arrays data structure, read about complex data structures here perldsc - Perl Data Structures Cookbook. Then the second step is simply read the data from the complex data structure and populate the graphs based on each line. Each graph name is based on the input file name and line number. You can play around with the name as you wish to modify them.

    Sample of code, sample of data and sample of output:

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: How to get data to an array?
by dbander (Scribe) on Aug 31, 2017 at 21:14 UTC

    The line you're likely looking for:

    my @data = split(',',$input_buffer);

    In context:

    #!/usr/bin/perl use strict; use warnings; my @histofeld = (); open my $input_file, '<', 'test.dat' or die "$!"; while (my $input_buffer = <$input_file>) { chomp $input_buffer; my @data = split(',',$input_buffer); push @histofeld, @data; } close $input_file;

      Hello dbander,

      Your solution unfortunately puts all data into the array. The OP will not be able to differentiate the data in order to create separate graphs.

      Sample of code and output:

      You should do something like that:

      Hope this helps, BR.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
        Hello!

        Thank you all very much.

        push @histofeld, [split ',', $tmp[$i]];
        This get it work. :)

        Regards, buchi