0

I am trying to create a perl script to load file contents into a dimensioned array and it does not seem to be working. Any help would be greatly appreciated!

This is what I am trying but it is not working.

#!/bin/perl
use List::Util qw(first);
@filelist = ("file1", "file2", "file3");

sub Load_File{
  my $File_Name = shift;
  open my $handle, '<', $File_Name;
  chomp( my @lines = <$handle>);
  close $handle;
  return @lines;
}


$filelist[0] = Load_File(@filelist[0]);

print "$filelist[0][1]\n";

My expected results would be for $filelist[0] to == "file1" and $filelist[0][0] to return the first line of the file with each subsequent sub-array entry being a line in the file.

Data format visualization

$filelist[0] == "file1"
$filelist[0][0] == "Line1 of file1"
$filelist[0][1] == "Line2 of file1"
$filelist[0][2] == "Line3 of file1"
$filelist[1] == "file2"
$filelist[1][0] == "Line1 of file2"
$filelist[1][1] == "Line2 of file2"
$filelist[1][2] == "Line3 of file2"
etc.

So what am I doing wrong?

Thank you

UPDATE/Clarification:

Thank you for the responses and clarification!

It looks like I am going about this wrong. I am trying to make an automatic random playlist generator. The intent was to set up text files which are just lists of song locations, each text file being a given genre. Then to have the script randomly select one or more songs from each genre and output a randomized M3U playlist. Allowing me to set some genre's to occur at given points. Like select 4 country songs, then 1 hard rock, then 3 of another.

My thought was to use the dimensioned array's then when an array was empty to remove it from the filelist. Using splice with rand to grab a song, remove it from the array, thus random selection would not slow down as it would be selecting from an ever smaller array.

From reading the responses I may have gone down a dead end and need to rethink how to solve it. Pointers are appreciated!

2
  • You must always use strict and use warnings 'all' at the top of every Perl program that you write Commented Mar 4, 2016 at 15:58
  • Re clarification: You might as well read all titles into one big list and select randomly from that. Two dimensions just complicate matters. Commented Mar 4, 2016 at 18:34

4 Answers 4

1

You can't get such structure in Perl (and many other languages for that matter). Each of your second level is actually a separate array and your first level array cells hold reference to those sub-arrays as value. So $filelist[0] = [ "Line1 of file1", "Line2 of file1", "Line3 of file1" ]. $filelist[0] can't be both "file1" and [...] at once.

(Well, it is Perl we're talking about, so actually you can, because with enough knowledge of internals you can do many insane things. But you really shouldn't go there at your level and even if you find out how to do that later, you shouldn't do that because it would be unreadable and unmantainable.)

Sign up to request clarification or add additional context in comments.

5 Comments

There is no standard for array processing in the Intel instruction set. But wait, are you saying that Perl doesn't support arrays of arrays, unless you write some C when it actually can? There are two prevalent ways of representing a multi-dimensional array. The first is the FORTRAN and C way of insisting on a fixed size for every dimension and doing simple arithmetic to locate an element within what is essentially a one-dimensional array. The other is to use references to arrays, so that an N-dimensional array requires that you follow N successive dereferences.
Reading again I think you meant something rather more simple, and assumed that the OP expects $filelist[0] to retain its value as the name of the first file while $filelist[0][1] is the contents of that file's first (second?) line. You may be right, but I hope not
I was actually expecting $filelist[0] to retain its value. I've been doing a lot of php programming lately and have gotten used to creating arrays of arrays in PHP
@Borodin, indeed. And OP explicitly lists it in both question text and data dump. Yes, this looks like just another XY problem, but as formulated right now it is not possible.
@Oleg V. Volkov your right, I have found it is not possible following the train of thought I was using. I have updated it with the end goal to see if someone point me in the right direction. Thank you for your clarification!
1

Load_File returns a list, so it should not be assigned to the scalar value $filelist[0]. Instead, assign it to a reference to the array returned by Load_File.

$filelist[0] = [ Load_File($filelist[0]) ];

1 Comment

This will of course clobber the 'file1' string from the array element.
1

You presumably want an array of arrays. Each element of a Perl array is a scalar value, which means that you must use array references if you want a second level of arrays

You could write something like this, which copies the list returned by load_file into an anonymous array and inserts that into @filelist

#!/bin/perl

use strict;
use warnings 'all';

my @filelist = qw/ file1 file2 file3 /;

sub load_file {
    my $file_name = shift;
    open my $handle, '<', $file_name;
    chomp( my @lines = <$handle> );
    return @lines;
}

$filelist[0] = [ load_file( @filelist[0] ) ];

print "$filelist[0][1]\n";

but it would be more efficient to alter load_file so that it returned a reference to its own array by writing

return \@lines;

and you can then keep the rest of your code as it was.

However, unless you need to call load_file more than once, it would be more Perlish to write this

#!/bin/perl

use strict;
use warnings 'all';

my @filelist = map {
    open my $fh, '<', $_;
    chomp ( my @lines = <$fh> );
    \@lines;
} qw/ file1 file2 file3 /;

print "$filelist[0][1]\n";

And are you sure your perl executable is at /bin/perl?

Comments

0

Your subroutine returns a list.

For a list to be an array element you have to store an array reference.

sub Load_File{
 # ...
   return \@lines;
}

And to access the first line, use index 0.

print "$filelist[0][0]\n";

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.