Как отделить слова в "предложении" с пробелами?
Фон
Глядя на автоматизацию создания доменов в JasperServer. Домены - это "представление" данных для создания специальных отчетов. Имена столбцов должны быть представлены пользователю понятным для пользователя способом.
Проблема
Есть более 2000 возможных данных, из которых организация теоретически может включить в отчет. Данные получены из не-человеческих имен, таких как:
payperiodmatchcode labordistributioncodedesc зависимая взаимосвязь действий actionendoptiondesc addresstype addresstypedesc historytype psaddresstype rolename bankaccountstatus bankaccountstatusdesc тип банковского счета bankaccounttypedesc beneficiaryamount выгодоприобретатель Преимущества Benefubiaryclass Benefificiaryclassdesc useactioncode benefitactioncodedesc benefitagecontrol benefitagecontroldesc ageconrolagelimit ageconrolnoticeperiod
Вопрос
Как вы автоматически измените такие имена на:
- код соответствия периода оплаты
- код распределения рабочей силы desc
- зависимая взаимосвязь
Идеи
-
Использовать Google Вы имели в виду движок, однако я думаю, что это нарушает их TOS:
lynx -dump «url» | grep "Did you mean" | awk ...
Языки
Любой язык в порядке, но текстовые синтаксические анализаторы, такие как 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/