Как разделить слова в «предложении» с пробелами? - PullRequest
11 голосов
/ 04 октября 2010

Фон

Хотите автоматизировать создание доменов в JasperServer. Домены - это «просмотр» данных для создания специальных отчетов. Имена столбцов должны быть представлены пользователю в удобочитаемой форме.

Проблема

Существует более 2000 возможных фрагментов данных, которые теоретически организация может захотеть включить в отчет. Данные получены из не дружественных человеку имен, таких как:

payperiodmatchcode labordistributioncodedesc зависимые отношения действияэндопция actionendoptiondesc addresstype addresstypedesc historytype psaddresstype rolename bankaccountstatus bankaccountstatusdesc bankaccounttype bankaccounttypedesc получатель получателькласс Преимущества подкласса выгодоприобретательский класс benefitactioncodedesc benefitagecontrol benefitagecontroldesc ageconrolagelimit ageconrolnoticeperiod

Вопрос

Как бы вы автоматически изменили такие имена на:

  • код совпадения периода оплаты
  • код распределения труда desc
  • зависимые отношения

Идеи

  • Используйте Google Вы имели в виду движок, однако я думаю, что он нарушает их TOS:

    lynx -dump «url» | grep "Did you mean" | awk ...

Языки

Подойдет любой язык, но парсеры текста, такие как Perl, вероятно, подойдут. (Имена столбцов только на английском языке.)

Ненужная префектура

Цель - не 100% совершенство в разделении слов; приемлем следующий результат:

  • enrollmenteffectivedate -> Дата вступления в силу
  • enrollmentenddate -> Enroll Men Tend Date
  • enrollmentrequirementset -> Набор требований для регистрации

Независимо от того, что человеку нужно будет перепроверить результаты и исправить многие. Сокращение набора из 2000 результатов до 600 изменений приведет к значительной экономии времени. Чтобы зафиксировать в некоторых случаях, имеющих несколько возможностей (например, имя терапевта), нужно полностью упустить момент.

Ответы [ 6 ]

14 голосов
/ 04 октября 2010

Иногда допускается брутфорс :

#!/usr/bin/perl

use strict; use warnings;
use File::Slurp;

my $dict_file = '/usr/share/dict/words';

my @identifiers = qw(
    payperiodmatchcode labordistributioncodedesc dependentrelationship
    actionendoption actionendoptiondesc addresstype addresstypedesc
    historytype psaddresstype rolename bankaccountstatus
    bankaccountstatusdesc bankaccounttype bankaccounttypedesc
    beneficiaryamount beneficiaryclass beneficiarypercent benefitsubclass
    beneficiaryclass beneficiaryclassdesc benefitactioncode
    benefitactioncodedesc benefitagecontrol benefitagecontroldesc
    ageconrolagelimit ageconrolnoticeperiod
);

my @mydict = qw( desc );

my $pat = join('|',
    map quotemeta,
    sort { length $b <=> length $a || $a cmp $b }
    grep { 2 < length }
    (@mydict, map { chomp; $_ } read_file $dict_file)
);

my $re = qr/$pat/;

for my $identifier ( @identifiers ) {
    my @stack;
    print "$identifier : ";
    while ( $identifier =~ s/($re)\z// ) {
        unshift @stack, $1;
    }
    # mark suspicious cases
    unshift @stack, '*', $identifier if length $identifier;
    print "@stack\n";
}

Выход:

payperiodmatchcode : pay period match code
labordistributioncodedesc : labor distribution code desc
dependentrelationship : dependent relationship
actionendoption : action end option
actionendoptiondesc : action end option desc
addresstype : address type
addresstypedesc : address type desc
historytype : history type
psaddresstype : * ps address type
rolename : role name
bankaccountstatus : bank account status
bankaccountstatusdesc : bank account status desc
bankaccounttype : bank account type
bankaccounttypedesc : bank account type desc
beneficiaryamount : beneficiary amount
beneficiaryclass : beneficiary class
beneficiarypercent : beneficiary percent
benefitsubclass : benefit subclass
beneficiaryclass : beneficiary class
beneficiaryclassdesc : beneficiary class desc
benefitactioncode : benefit action code
benefitactioncodedesc : benefit action code desc
benefitagecontrol : benefit age control
benefitagecontroldesc : benefit age control desc
ageconrolagelimit : * ageconrol age limit
ageconrolnoticeperiod : * ageconrol notice period

См. Также Проверка орфографии, которая раньше была основным достижением разработки программного обеспечения .

1 голос
/ 08 октября 2010

Вот программа Lua, которая выбирает самые длинные совпадения из словаря:

local W={}
for w in io.lines("/usr/share/dict/words") do
    W[w]=true
end

function split(s)
    for n=#s,3,-1 do
        local w=s:sub(1,n)
        if W[w] then return w,split(s:sub(n+1)) end
    end
end

for s in io.lines() do
    print(s,"-->",split(s))
end
1 голос
/ 05 октября 2010

Мне приходят на ум две вещи:

  • это не та задача, которую вы можете уверенно атаковать программно, потому что ... английские слова не работают так, они часто состоятДругими словами, является ли данная строка "репортаж" или "отчетный возраст"?«Часы» или «часы»?
  • Один из способов атаковать проблему - использовать anag, который находит анаграммы.В конце концов, «timepiece» - это анаграмма «timepiece» ... теперь вам просто нужно отсеять ложные срабатывания.
1 голос
/ 04 октября 2010

Я сократил ваш список до 32 атомарных терминов, которые меня интересовали, и поместил их в регулярное выражение в регулярном выражении:

use strict;
use warnings;

my $qr 
    = qr/ \G # right after last match
          ( distribution 
          | relationship 
          | beneficiary 
          | dependent 
          | subclass 
          | account
          | benefit 
          | address 
          | control 
          | history
          | percent 
          | action 
          | amount
          | conrol 
          | option 
          | period 
          | status 
          | class 
          | labor 
          | limit 
          | match 
          | notice
          | bank
          | code 
          | desc 
          | name 
          | role 
          | type 
          | age 
          | end 
          | pay
          | ps 
          )
    /x;

while ( <DATA> ) { 
    chomp;
    print;
    print ' -> ', join( ' ', m/$qr/g ), "\n";
}

__DATA__
payperiodmatchcode
labordistributioncodedesc
dependentrelationship
actionendoption
actionendoptiondesc
addresstype
addresstypedesc
historytype
psaddresstype
rolename
bankaccountstatus
bankaccountstatusdesc
bankaccounttype
bankaccounttypedesc
beneficiaryamount
beneficiaryclass
beneficiarypercent
benefitsubclass
beneficiaryclass
beneficiaryclassdesc
benefitactioncode
benefitactioncodedesc
benefitagecontrol
benefitagecontroldesc
ageconrolagelimit
ageconrolnoticeperiod
0 голосов
/ 04 сентября 2013

Питер Норвиг имеет отличный скрипт на python, который имеет функцию сегментации слов с использованием статистики unigram / bigram. Вы хотите взглянуть на логику для функции сегмент2 в ngrams.py. Подробности в главе «Корпус естественных языков» из книги «Красивые данные» (Segaran and Hammerbacher, 2009). http://norvig.com/ngrams/

0 голосов
/ 04 октября 2010

Учитывая, что некоторые слова могут быть подстрока других, особенно с несколькими словами, слитых вместе, я думаю, что простые решения, такие как регулярные выражения, отсутствуют. Я бы пошел с полноценным парсером, мой опыт работы с ANTLR. Если вы хотите придерживаться Perl, мне повезло, используя парсеры ANTLR, сгенерированные как Java через Inline :: Java.

...