koleti has asked for the wisdom of the Perl Monks concerning the following question:
hello Monks,
I have a file containing list like this
IL12::1::287,6,-17,-9,-21,-24,-15,-2,11,4,4,-15,-26,-16,-9,-18,-25,27,17,6,
IL12::1::329,-25,-18,-28,23,17,1,-3,-23,
IL12::1::1108,-8,-21,17,-25,9,-6,-15,4,
IL12::1::1536,-12,-28,23,-12,17,-25,14,19,20,
IL12::1::1591,-17,-23,-7,-19,25,25,-25,-15,-26,23,29,-12,-25,
IL12::1::803,24,-20,-24,12,8,-22,
now i want to make each line as an array and give the first one as the name of the
like this
@IL12::1::287 = ('6','-17','-9','-21','-24','-15','-2','11','4','4','-15','-26','-16','-9','-18','-25','27','17','6')
and the i want to compare 2 arrays to find the common elements in it
Re: how to make first element of an string as a the array name
by thezip (Vicar) on Nov 15, 2007 at 00:13 UTC
|
Why not make it a hash of array references, as in:
use strict;
use warnings;
use Data::Dumper;
my $hash = {
'IL12::1::287' => [6,-17,-9,-21,-24,-15,-2,11,4,4,-15,-26, ...],
'IL12::1::329' => [-25,-18,-28,23,17,1,-3,-23],
...
}
print Dumper($hash);
You'll need to split each line and shift off the first element to get the hash
key (ie. 'IL12::1::287').
I'm not sure which lines you're going to compare. Could you please explain this more?
Where do you want *them* to go today?
| [reply] [Watch: Dir/Any] [d/l] |
Re: how to make first element of an string as a the array name
by erroneousBollock (Curate) on Nov 15, 2007 at 00:13 UTC
|
First you need to parse your file. What have you already tried? Can we see your code?
(When you post your code, please remember to read the Writeup Formatting Tips.)
now i want to make each line as an array and give the first one as the name of the
like this
@IL12::1::287 = ('6','-17','-9','-21','-24','-15','-2','11','4','4','-15','-26','-16','-9','-18','-25','27','17','6')
Please don't use variables as variable names (yes this still applies).
Second, you'd do better to store your arrays as references in a hash, where the keys to the hash could be 'IL12::1::287', 'IL12::1::329', etc.
(Update: thezip gives you an example of the data-structure below.)
As for the array "common elements" problem, the usual way to solve that is to build a hash containing the elements of the first array as keys, then to loop through the elements of the second array testing for existence in the hash.
# you have @arr1 and @arr2
my %lookup = map { $_ => undef } @arr1;
my @common = grep { exists $lookup{$_} } @arr2;
-David
| [reply] [Watch: Dir/Any] [d/l] |
Re: how to make first element of an string as a the array name
by GrandFather (Saint) on Nov 15, 2007 at 02:10 UTC
|
You might want to tell us a little more about the problem you are trying to solve because your current solution is almost never the right way to do it.
It seems most likely that what you really need is a hash. Consider:
use strict;
use warnings;
use List::Compare;
my $fileData = <<DATA;
IL12::1::287,6,-17,-9,-21,-24,-15,-2,11,4,4,-15,-26,-16,-9,-18,-25,27,
+17,6,
IL12::1::329,-25,-18,-28,23,17,1,-3,-23,
IL12::1::1108,-8,-21,17,-25,9,-6,-15,4,
IL12::1::1536,-12,-28,23,-12,17,-25,14,19,20,
IL12::1::1591,-17,-23,-7,-19,25,25,-25,-15,-26,23,29,-12,-25,
IL12::1::803,24,-20,-24,12,8,-22,
DATA
my %items;
my $referenceItem = 'IL12::1::287';
open my $inFile, '<', \$fileData;
while (<$inFile>) {
chomp;
my ($item, @values) = split ',';
$items{$item} = \@values;
}
for my $key (sort keys %items) {
next if $key eq $referenceItem;
my @common = List::Compare->new ($items{$referenceItem}, $items{$k
+ey})
->get_intersection ();
print "Common for $key: @common\n" if @common;
}
Prints:
Common for IL12::1::1108: -15 -21 -25 17 4
Common for IL12::1::1536: -25 17
Common for IL12::1::1591: -15 -17 -25 -26
Common for IL12::1::329: -18 -25 17
Common for IL12::1::803: -24
Perl is environmentally friendly - it saves trees
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: how to make first element of an string as a the array name
by Anonymous Monk on Nov 15, 2007 at 00:32 UTC
|
You probably really want a hash...
#!/usr/bin/perl -w
use strict;
my %lines;
open my $file, "<data.txt" or die "can't open: $!";
while(<$file>)
{
(my $key, my $stuff) = m/^([^,]*),(.*)/;
my @data = split(",", $stuff);
$lines{$key} = \@data;
}
# do something...
print @{$lines{"IL12::1::329"}};
| [reply] [Watch: Dir/Any] [d/l] |
|
By simple parsing i could make the file look like this
@IL12::1::287 = qw(6 -17 -9 -21 -24 -15 -2 11 4 4 -15 -26 -16 -9 -18 -25 27 17 6);
@IL12::1::329 = qw(-25 -18 -28 23 17 1 -3 -23);
@IL12::1::1108 = qw(-8 -21 17 -25 9 -6 -15 4);
@IL12::1::1536 = qw(-12 -28 23 -12 17 -25 14 19 20);
@IL12::1::1591 = qw(-17 -23 -7 -19 25 25 -25 -15 -26 23 29 -12 -25);
@IL12::1::803 = qw(24 -20 -24 12 8 -22);
@IL12::1::1483 = qw(-20 -4 24 -17 19 -19 8 11 -5);
@IL12::1::631 = qw(-6 -22 19 26 -22);
@IL12::1::817 = qw(-23 -12 -15 -19 18 18 -23 8 -8 -8 8 4);
now my file contains list of arrays
i want to call 2 or more arrays from that file and use List::Compare to compare the arrays
how could i do that
is there any way to call a particular array from a file
| [reply] [Watch: Dir/Any] |
Re: how to make first element of an string as a the array name
by radiantmatrix (Parson) on Nov 15, 2007 at 17:04 UTC
|
I don't think you really want to have the first element be a real array name -- do you have a package named IL12::1 ? If you want to reference these things by name, I suggest (as others have) a hash, with the first element of each row in your file being the key.
Text::CSV_XS would work wonderfully for this application.
#!/usr/bin/perl
use strict; use warnings;
use IO::File;
use Text::CSV_XS;
use Data::Dumper;
my $io = IO::File->new('myinputfile.txt','<')
or die "Cannot open input file for reading: $!";
my $csv = Text::CSV_XS->new();
my %data;
while (my $row = $csv->getline($io)) {
# getline() reads a line from $io and parses it -- fast!
# $row will contain an ARRAYref, one value for each element
my $element_name = shift @$row; #first element is the name
$data{$element_name} = $row;
}
print Dumper(\%data); # this will show you how the structure looks
The output from this should look like:
$VAR1 = {
'IL12::1::287' => [
'6',
'-17',
'-9',
'-21',
'-24',
'-15',
'-2',
'11',
'4',
'4',
'-15',
'-26',
'-16',
'-9',
'-18',
'-25',
'27',
'17',
'6'
]
...
};
(I've used ... to indicate that there will be more of the same, to save space in this node)
I hope that helps!
<–radiant.matrix–>
Ramblings and references
The Code that can be seen is not the true Code
I haven't found a problem yet that can't be solved by a well-placed trebuchet
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|