How to retain only unique elements?

S

Sagar S

Hello all,

I am a newbie to Perl and now I am stuck with a problem (which may seem
simple to all the Perl Gurus out there ;-) )
I am having a list like (XYZ_A(8::7), XYZ_B(4,15), XYZ_C(4,6), XYZ_A(8,9),
XYZ_A(6,15), XYZ_B(8,10) ) for example.
The problem is I have to retain only one element of each kind (XYZ_A, XYZ_B,
XYZ_C etc) such that for each kind, only those which have the lowest first
number are retained. I mean, after processing, the list should be
(XYZ_B(4,15), XYZ_C(4,6), XYZ_A(6,15))

I will really appreciate any help in this direction, probably a code snippet
or some hints atleast.
 
P

Paul Lalli

Sagar said:
I am a newbie to Perl and now I am stuck with a problem (which may seem
simple to all the Perl Gurus out there ;-) )
I am having a list like (XYZ_A(8::7), XYZ_B(4,15), XYZ_C(4,6), XYZ_A(8,9),
XYZ_A(6,15), XYZ_B(8,10) ) for example.

That is not an example. That's not Perl code. I have no idea what
your list actually contains. Please speak Perl, not English.
The problem is I have to retain only one element of each kind (XYZ_A, XYZ_B,
XYZ_C etc) such that for each kind, only those which have the lowest first
number are retained. I mean, after processing, the list should be
(XYZ_B(4,15), XYZ_C(4,6), XYZ_A(6,15))

I will really appreciate any help in this direction, probably a code snippet
or some hints atleast.

What have you tried so far? How did it fail to work for you?

If you have a list of strings, first define a hash whose key is the
unique identifier and whose value is the whole string. Loop through
that list, parse out the unique identifier and the first number, using
a regular expression. Compare the first number of the current string
to the first number of the saved value in the hash. If the current
string is lower, save the current string to the hash. When the loop is
done, your unique values will be found from the values() function, with
your hash as an argument.

Once you've made an attempt, if it doesn't work, post a
short-but-complete script here, and we can probably help you fix it.

Paul Lalli
 
T

Tad McClellan

Sagar S said:
I am a newbie to Perl and now I am stuck with a problem (which may seem
simple to all the Perl Gurus out there ;-) )


Please see the Posting Guidelines that are posted here frequently.

I am having a list like (XYZ_A(8::7), XYZ_B(4,15), XYZ_C(4,6), XYZ_A(8,9),
XYZ_A(6,15), XYZ_B(8,10) ) for example.


That is not a Perl list.

Please post Real Perl Code.

The problem is I have to retain only one element of each kind (XYZ_A, XYZ_B,
XYZ_C etc)


Since your problem does not seem to be how to get such a list in
Perl code, then you should have been able to post it in Perl code.

such that for each kind, only those which have the lowest first
number are retained. I mean, after processing, the list should be
(XYZ_B(4,15), XYZ_C(4,6), XYZ_A(6,15))


If they must be in that order, then the problem gets a good bit harder...

I will really appreciate any help in this direction,


Please indicate what you need help with, and what part you already
know how to do.

The best and easiest way to show the parts that you already know how
to do is to post the Perl code that does it.

Do we need to help you create the list?

Do we need to help you extract the 2 "interesting" parts from
each list item?

Do we need to help you track which one is the least for each "name"?

Do we need to help you with the print() statement for making the
final output?


You will be much more likely to get a little help rather than get
a lot of help.

A blanket "help me" makes the task of helping so large that many
or most potential answers will just move on to helping the next
poster instead.

I just happen to have more time than usual today, or I would have
done that too. :)

probably a code snippet
or some hints atleast.


This is a much too intricate problem for an early Perl programmer
to tackle. You'll need to learn many different things before you'll
be able to do it.

Choose a simpler problem first, move to more complex problems after
you have at least a bit of experience.

The primare elements of solving your problem are to use a m// in
a list context to pluck out the 2 interesting parts, and a
multi-level hash to record each of the 3 parts.

Multi-dimensional data structures are not a "beginning" topic...


--------------------------------
#!/usr/bin/perl
use warnings;
use strict;

my @array = ( 'XYZ_A(8::7)',
'XYZ_B(4,15)',
'XYZ_C(4,6)',
'XYZ_A(8,9)',
'XYZ_A(6,15)',
'XYZ_B(8,10)',
);

my %least; # keep track of the least number for each
foreach my $item ( @array ) {
my($name, $num) = $item =~ /([^(]+) # up 'til the 1st paren goes in $1
\( # opening paren
(\d+) # some digits go in $2
/x;

if ( !exists $least{ $name } ) { # 1st time we've seen this one
$least{ $name }{ num } = $num;
$least{ $name }{ item } = $item;
next; # done recording this one
}

if ( $num < $least{ $name }{ num } ) { # need to update
$least{ $name }{ num } = $num;
$least{ $name }{ item } = $item;
}
}

print "$least{ $_ }{ item }\n" for sort keys %least;
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,201
Messages
2,571,051
Members
47,656
Latest member
rickwatson

Latest Threads

Top