简体   繁体   English

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

[英]How do I find the case-insensitive unique elements of two arrays in Perl?

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

Do you only want the unique elements from @array2 ? 您只需要@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: 首先初始化值为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: 当您需要尚未处理的曲目时,请选择值不为true的关键点:

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

Whenever you have a question about your items, you just ask %Tracks the right question. 每当您对商品有疑问时,只需问%Tracks正确的问题。

这应该可以解决问题。

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

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的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM