Как отделить слова в "предложении" с пробелами?

Фон

Глядя на автоматизацию создания доменов в JasperServer. Домены - это "представление" данных для создания специальных отчетов. Имена столбцов должны быть представлены пользователю понятным для пользователя способом.

Проблема

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

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

Вопрос

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

  • код соответствия периода оплаты
  • код распределения рабочей силы desc
  • зависимая взаимосвязь

Идеи

Языки

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

Ненужная предварительная проверка

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

  • enrollmenteffectivedate → Дата вступления в силу регистрации
  • enrollmentenddate → Дата регистрации людей для регистрации
  • enrollmentrequirementset → Набор требований к регистрации

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

Ответы

Ответ 1

Иногда bruteforcing приемлемо:

#!/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

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

Ответ 2

Я сократил список до 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

Ответ 3

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

  • Это просто не задача, которую вы можете уверенно атаковать программно, потому что... Английские слова не работают так, они часто сделаны из других слов, поэтому данная строка представляет собой "репортаж" или "отчет возраст"? "Часы" или "Временная диаграмма"?
  • Одним из способов решения этой проблемы будет использование anag, который находит анаграммы. В конце концов, "time piece" является анаграммой "часов" ... теперь вам просто нужно отсеять ложные срабатывания.

Ответ 4

Вот программа 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

Ответ 5

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

Ответ 6

Питер Норвиг имеет отличный python script, который имеет функцию сегментации слов, используя статистику униграмм /bigram. Вы хотите взглянуть на логику для функции segment2 в ngrams.py. Подробности приведены в главе Natural Language Corpus Data из книги "Прекрасные данные" (Segaran and Hammerbacher, 2009). http://norvig.com/ngrams/