Hal ini sangat mirip dengan jawaban @ meuh ini, tapi bukannya menambahkan foreach
lingkaran setelah split
line, Anda hanya perlu menambahkan satu baris ada, baik menggunakan perl
's grep
fungsi atau nya map
fungsi:
@titlewords = grep (!/^(and|if|the)$/i, @titlewords);
atau
@titlewords = map { /^(and|if|the)$/i ? () : $_ } @titlewords;
Lihat perldoc -f grep
dan perldoc -f map
untuk detail lebih lanjut tentang fungsi-fungsi ini dan perbedaan di antara mereka. Mereka biasanya digunakan (terutama map
) dalam banyak perl
skrip, jadi ada baiknya meluangkan waktu untuk memahami apa yang mereka lakukan dan mempelajari cara kerjanya.
BTW, JANGAN gunakan #!/usr/bin/env perl
. Menggunakan env
seperti itu cukup dengan buruk python
dan ruby
skrip (di mana itu, sayangnya, konvensi), tapi itu benar-benar rusak untuk perl
script dan pasti tidak dengan cara konvensional untuk menjalankannya.
perl
memiliki banyak opsi baris perintah yang mengubah perilakunya dalam cara yang signifikan, tergantung pada jenis program yang Anda coba tulis. Menggunakan env
untuk menjalankan juru bahasa seperti perl
benar - benar menghancurkan kemampuan untuk meneruskan opsi baris perintah ke juru bahasa (karena env
tidak mendukungnya. env
Bahkan tidak dirancang untuk digunakan untuk tujuan ini, melakukannya hanya peretasan jelek yang mengambil keuntungan dari efek samping dari env
tujuan aktual - yaitu mengatur variabel lingkungan sebelum menjalankan program).
Gunakan #!/usr/bin/perl
sebaliknya (atau apa pun jalan menuju perl
penerjemah Anda ).
Berikut skrip perl lain yang melakukan apa yang Anda inginkan - tetapi ini menggunakan skrip Class::CSV
dan List::Compare
modul, serta dua Hash-of-Array untuk membandingkan file CSV:
#! /usr/bin/perl
use strict;
use warnings;
use Class::CSV;
use List::Compare;
sub parse_csv($%) {
my($filename,$tw) = @_;
# exclude the following word list and the "empty word"
my @exceptions = qw(and if the);
my $exceptions = '^(\s*|' . join('|',@exceptions) . ')$';
my $csv = Class::CSV->parse(
filename => $filename,
fields => [qw/id title num1 num2/]
);
# build a hash-of-arrays (HoA), keyed by the CSV line. Each array
# contains the individual words from each title for that line (except
# for those matching $exceptions). The words are all converted to
# lowercase to enable case-insensitive matches.
foreach my $line (@{$csv->lines()}) {
# The following three lines are required because the input file has
# fields separated by ', ' rather than just ',' which makes
# Class::CSV interpret the numeric fields as strings.
# It's easier/quicker to do this than to rewrite using Text::CSV.
#
# The final output will be properly-formed CSV, with only a comma as
# field separator and quotes around the title string.
my $key = join(',',$line->id,'"'.$line->title.'"',$line->num1,$line->num2);
$key =~ s/([",])\s+/$1/g; # trim whitespace immediately following " or ,
$key =~ s/\s+([",])/$1/g; # trim whitespace immediately preceding " or ,
# If it wasn't for the not-quite-right CSV format, we could just use:
#my $key = $line->string;
push @{ $tw->{$key} }, grep (!/$exceptions/oi, split(/\s+/,$line->title));
};
};
# two hashes to hold the titlewords HoAs
my %tw1=();
my %tw2=();
parse_csv('csv1',\%tw1);
parse_csv('csv2',\%tw2);
# now compare the HoAs
foreach my $k2 (sort keys %tw2) {
my @matches = ();
foreach my $k1 (sort keys %tw1) {
my $lc = List::Compare->new('-u', \@{ $tw2{$k2} }, \@{ $tw1{$k1} });
push @matches, $k1 if ($lc->get_intersection ge 3);
};
print join("\n",sort(@matches,$k2)),"\n\n" if (@matches);
};
Keluaran:
11,"The Sun Still Shines in Reading",64312,464566
97,"Reading Still Shines",545464,16748967
Setiap kelompok kecocokan diurutkan dan, meskipun output sampel tidak menunjukkannya (karena hanya ada satu kelompok kecocokan), masing-masing kelompok dicetak sebagai paragraf terpisah (yaitu dipisahkan oleh baris kosong)
BTW, jika Anda tidak ingin tanda kutip ganda di sekitar bidang judul, edit my $key=join(...)
baris yang menambahkannya sehingga tidak.
perl
naskah dalam jawaban saya di bawah ini juga menjawab pertanyaan Anda baru saja dihapus. Theget_intersection
Metode dariList::Compare
modul menghilangkan entri ganda (yang adalah apa yang Anda harapkan dari set persimpangan), kata-kata individu dihitung hanya sekali untuk setiap judul. Ini adalah salah satu manfaat besar menggunakan modul perpustakaan yang ada daripada menulis sendiri - mereka biasanya menyertakan fitur yang berguna yang akan membutuhkan banyak upaya untuk mengimplementasikan diri Anda. Mereka juga cenderung telah menyelesaikan sebagian besar atau semua masalah umum (dan banyak yang tidak terlalu umum) terkait dengan tugas yang dihadapi.