如何在Perl中找到两个数组的不区分大小写的唯一元素?

时间:2021-11-19 19:25:41

I have three arrays.

我有三个阵列。

  • @array1 containing filenames
  • @ array1包含文件名

  • @array2 containing filenames
  • @ array2包含文件名

  • @unique which I want to contain the unique items
  • @unique我想要包含唯一的项目

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.

我需要的是结果只返回轨道10,14和05,因为第一个轨道,b-corrupt,已经在旧轨道阵列中,只是情况不同。

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";
}

4 个解决方案

#1


@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:

如果要将@new_ones列表添加到@ array1中已有的列表,从而生成到目前为止看到的所有唯一项的列表:

push @array1, @new_ones;

#2


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:

你只想要@ array2中的独特元素吗?如果你想要两个数组中的所有独特元素,你只需要浏览所有元素并记住你之前看过的元素:

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:

您发布了一个更新,您说您要选择尚未处理的元素。而不是两个数组,考虑一个哈希将所有数据保存在一个地方。首先使用值0初始化所有内容:

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

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

处理(或播放)其中一个元素时,将其哈希值设置为true值:

$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.

每当您对自己的商品有疑问时,只需询问%Tracks正确的问题即可。

#3


This should do the trick..

这应该做的伎俩..

    $test{lc $_} = 1 foreach @array1;  @unique = grep { ! exists $test{lc $_}} @array2;

#4


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

虽然我一般同意brian的%Seen解决方案,但我在原始问题中注意到输出显示了正确的歌曲标题。

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.

然后在输出中使用%title的内容。

#1


@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:

如果要将@new_ones列表添加到@ array1中已有的列表,从而生成到目前为止看到的所有唯一项的列表:

push @array1, @new_ones;

#2


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:

你只想要@ array2中的独特元素吗?如果你想要两个数组中的所有独特元素,你只需要浏览所有元素并记住你之前看过的元素:

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:

您发布了一个更新,您说您要选择尚未处理的元素。而不是两个数组,考虑一个哈希将所有数据保存在一个地方。首先使用值0初始化所有内容:

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

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

处理(或播放)其中一个元素时,将其哈希值设置为true值:

$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.

每当您对自己的商品有疑问时,只需询问%Tracks正确的问题即可。

#3


This should do the trick..

这应该做的伎俩..

    $test{lc $_} = 1 foreach @array1;  @unique = grep { ! exists $test{lc $_}} @array2;

#4


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

虽然我一般同意brian的%Seen解决方案,但我在原始问题中注意到输出显示了正确的歌曲标题。

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.

然后在输出中使用%title的内容。