tags:

views:

530

answers:

5

I have three arrays.

  • @array1 containing filenames
  • @array2 containing filenames
  • @unique which I want to contain the unique items

I use the following code to compare the two arrays and output a third array that contains the unique filenames.

@test{@array1} = ();
@unqiue = grep {!exists $test{$_}} @array2;

However the output is case sensitive, how do I change it to be case insensitive?

Thanks


Hi, Sorry I think I didnt ask my question very well!

I keep an old track array containing tracks I've already played and I then have a new track array I want to select from. I want to compare the new tracks against the old track array to ensure that I only get tracks that are unique to then choose from.

So currently the output is;

Unique Tracks:
\my Music\Corrupt Souls\b-corrupt.mp3
\My Music\gta4\10 - Vagabond.mp3
\My Music\gta4\14 - War Is Necessary.mp3
\My Music\Back To Black\05 Back to Black.mp3

What I need is for the result to just return track 10, 14, and 05 as the first track, b-corrupt, is already in the old track array only the case is different.

Thanks in advance for your help


#!/usr/bin/perl
$element = '\\My Music\\Corrupt Souls\\b-corrupt.mp3';
push (@oldtrackarray, $element);

$element = '\\My Music\\Back To Black\\03 Me and Mr Jones.mp3';
push (@oldtrackarray, $element);

$element = '\\My Music\\Jazz\\Classic Jazz-Funk Vol1\\11 - Till You Take My Love [Original 12 Mix].mp3';
push (@oldtrackarray, $element);

$element = '\\My Music\\gta4\\01 - Soviet Connection (The Theme From Grand Theft Auto IV).mp3';
push (@oldtrackarray, $element);

$element = '\\My Music\\gta4\\07 - Rocky Mountain Way.mp3';
push (@oldtrackarray, $element);

$element = '\\My Music\\gta4\\02 - Dirty New Yorker.mp3';
push (@oldtrackarray, $element);

print "Old Track Array\n";
for($index=0; $index<@oldtrackarray+1; $index++) {
    print "$oldtrackarray[$index]\n";}


$element = '\\my Music\\Corrupt Souls\\b-corrupt.mp3';
push (@newtrackarray, $element);

$element = '\\My Music\\gta4\\10 - Vagabond.mp3';
push (@newtrackarray, $element);

$element = '\\My Music\\gta4\\14 - War Is Necessary.mp3';
push (@newtrackarray, $element);

$element = '\\My Music\\Back To Black\\05 Back to Black.mp3';
push (@newtrackarray, $element);

print "New Tracks\n";
for($index=0; $index<@newtrackarray+1; $index++) {
    print "$newtrackarray[$index]\n";
}

@test{@oldtrackarray} = ();
@uninvited = grep {!exists $test{$_}} @newtrackarray;

print "Unique Tracks:\n";
for($index=0; $index<$#uninvited+1; $index++) {
    print "$uninvited[$index]\n";
}

+8  A: 
@test{ map { lc } @array1 } = ();
@new_ones = grep { !exists $test{lc $_} } @array2;

If you want to add the list of @new_ones to those already in @array1, thereby producing a list of all unique items seen so far:

push @array1, @new_ones;
j_random_hacker
+1  A: 

This should do the trick..

    $test{lc $_} = 1 foreach @array1;  @unique = grep { ! exists $test{lc $_}} @array2;
clintp
+5  A: 

Do you only want the unique elements from @array2? If you want all unique elements from both arrays, you just have to go through all elements and remember which ones you've seen before:

my %Seen = ();
my @unique = grep { ! $Seen{ lc $_ }++ } @array1, @array2;

You posted an update where you say you want to choose elements you haven't yet processed. Instead of two arrays, consider one hash to keep all of your data in one place. Start by initializing everything with a value of 0:

my %Tracks = map { $_, 0 } @all_tracks;

When you process (or play) one of the elements, set its hash value to a true value:

$Tracks{ $playing } = 1;

When you want the tracks that you haven't processed, select the keys where the value is not true:

@not_processed = grep { ! $Tracks{$_} } keys %Tracks;

Whenever you have a question about your items, you just ask %Tracks the right question.

brian d foy
A: 

Hi, Sorry I think I didnt ask my question very well!

long clarification moved to question

Instead of posting an answer, edit your original question. :)
brian d foy
A: 

Although I agree with brian's %Seen solution generally, I noticed in the original question that the output shows the proper-cased song titles.

A second hash (ie an inside-out design), along the lines of:

my %title;
foreach (@array1, @array2) {
    my $lc = lc $_;
    $title{$lc} = $_ unless $title{$lc} && $title{$lc} =~/[:upper:][:lower:]/;
        # ie don't overwrite if saved title matches '[A-Z][a-z]'
}

Then use the contents of %title in the output.

RET