كيف يمكنني مطابقة ترتيب السلسلة بين وثيقتين في بيرل؟

StackOverflow https://stackoverflow.com/questions/2894213

  •  04-10-2019
  •  | 
  •  

سؤال

لدي مشكلة في صنع برنامج Perl لمطابقة الكلمات في مستندتين. دعنا نقول أن هناك مستندات A و B.

لذلك أريد حذف الكلمات في الوثيقة A ليست في المستند B.

مثال 1:

ج: أنا آكل البيتزا

ب: تذهب إلى السوق وتناول البيتزا

النتيجة: أكل البيتزا

مثال 2: ج: أكل البيتزا

ب: بيتزا تأكل

النتيجة: البيتزا (ترتيب الكلمة ذات صلة ، لذلك يتم حذف "تناول الطعام".)

أستخدم Perl للنظام والجمل في كل مستند ليست بأعداد كبيرة ، لذلك أعتقد أنني لن أستخدم SQL

والبرنامج هو subproram لتصنيف المقالات التلقائية للغة الإندونيسية (بهاسا)

شكرا ، آسف إذا كان سؤالي مربكا بعض الشيء. أنا جديد حقًا على "هذا العالم" :)

هل كانت مفيدة؟

المحلول

حسنًا ، أنا بدون وصول في الوقت الحالي ، لذلك لا يضمن هذا 100 ٪ أو حتى الترجمة ولكن يجب أن توفر إرشادات كافية:

الحل 1: (ترتيب الكلمات لا يهم)

#!/usr/bin/perl -w

use strict;
use File::Slurp;

my @B_lines = File::Slurp::read_file("B") || die "Error reading B: $!";
my %B_words = ();
foreach my $line (@B_lines) {
    map { $B_words{$_} = 1 } split(/\s+/, $line);
}
my @A_lines = File::Slurp::read_file("A") || die "Error reading A: $!";
my @new_lines = ();
foreach my $line (@A_lines) {
    my @B_words_only = grep { $B_words{$_} } split(/\s+/, $line);
    push @new_lines, join(" ", @B_words_only) . "\n";
}
File::Slurp::write_file("A_new", @new_lines) || die "Error writing A_new: $!";

يجب أن ينشئ هذا ملفًا جديدًا "a_new" يحتوي فقط على كلمات A الموجودة في B.

هذا يحتوي على خلل طفيف - سيحل محل أي مسافة متعددة في ملف A بمساحة واحدة ، لذلك

    word1        word2              word3

سيصبح

word1 word2 word3

يمكن إصلاحه ولكن سيكون مزعجًا حقًا للقيام بذلك ، لذلك لم أكن أزعجني ما لم تكن ترغب في الحفاظ على مساحة البيضاء بنسبة 100 ٪ بشكل صحيح

الحل 2: (أمر الكلمات مهم ولكن يمكنك طباعة الكلمات من ملف A Out دون أي معيات للحفاظ على مساحة البيضاء على الإطلاق)

#!/usr/bin/perl -w

use strict;
use File::Slurp;

my @A_words = split(/\s+/gs, File::Slurp::read_file("A") || die "Error reading A:$!");
my @B_words = split(/\s+/gs, File::Slurp::read_file("B") || die "Error reading B:$!");
my $B_counter = 0;
for (my $A_counter = 0; $A_counter < scalar(@A_words); ++$A_counter) {
    while ($B_counter < scalar(@B_words)
        && $B_words[$B_counter] ne $A_words[$A_counter]) {++$B_counter;}
    last if $B_counter == scalar(@B_words);
    print "$A_words[$A_counter]";
}

الحل 3 (لماذا نحتاج بيرل مرة أخرى؟ :))

يمكنك القيام بذلك بشكل تافه في Shell بدون Perl (أو عبر System () الاتصال أو backticks في البرنامج النصي Perl Perl)

comm -12 A B | tr "\012" " " 

لاستدعاء هذا من بيرل:

my $new_text = `comm -12 A B | tr "\012" " " `;

لكن راجع تعليقي الأخير لماذا يمكن اعتبار ذلك "سيئًا بيرل" ... على الأقل إذا قمت بذلك في حلقة مع تكرار العديد من الملفات وتهتم بالأداء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top