Как я могу разделить несколько слов, к которым присоединяются?

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

46
задан Henk Holterman 6 May 2012 в 07:34
поделиться

7 ответов

Человек может сделать это?

farsidebag
far sidebag
farside bag
far side bag

Мало того, что необходимо использовать словарь, Вам, возможно, придется использовать статистический подход для выяснения то, что наиболее вероятно (или, бог запрещает, фактический HMM для предпочтительного естественного языка...),

Поскольку, как сделать статистику, которая могла бы быть полезной, я оказываюсь Вами к доктору Peter Norvig, который решает другую, но связанную проблему проверки правописания в 21 строке кода: http://norvig.com/spell-correct.html

(он действительно обманывает немного путем сворачивания каждого для цикла в одну строку.. но все еще).

Обновите Это застряло в моей голове, таким образом, у меня была к рождению она сегодня. Этот код делает подобное разделение к тому, описанному Robert Gamble, но затем это заказывает результаты на основе частотности слова в обеспеченном файле словаря (который, как теперь ожидают, будет некоторым текстовым представителем Вашего домена или англичанами в целом. Я использовал big.txt от Norvig, связанного выше, и catted словарь к нему, для покрытия недостающих слов).

Комбинация двух слов большую часть времени разобьет комбинацию 3 слов, если различие частоты не будет огромно.


Я отправил этот код с некоторыми незначительными изменениями на моем блоге

http://squarecog.wordpress.com/2008/10/19/splitting-words-joined-into-a-single-string/ и также записал немного об ошибке потери значимости в этом коде.. Я испытал желание просто, бесшумно фиксируют его, но полагал, что это может помочь некоторым людям, которые не видели прием журнала прежде: http://squarecog.wordpress.com/2009/01/10/dealing-with-underflow-in-joint-probability-calculations/


Вывод на Ваших словах, плюс некоторые мои собственные - замечают то, что происходит с "orcore":

perl splitwords.pl big.txt words
answerveal: 2 possibilities
 -  answer veal
 -  answer ve al

wickedweather: 4 possibilities
 -  wicked weather
 -  wicked we at her
 -  wick ed weather
 -  wick ed we at her

liquidweather: 6 possibilities
 -  liquid weather
 -  liquid we at her
 -  li quid weather
 -  li quid we at her
 -  li qu id weather
 -  li qu id we at her

driveourtrucks: 1 possibilities
 -  drive our trucks

gocompact: 1 possibilities
 -  go compact

slimprojector: 2 possibilities
 -  slim projector
 -  slim project or

orcore: 3 possibilities
 -  or core
 -  or co re
 -  orc ore

Код:

#!/usr/bin/env perl

use strict;
use warnings;

sub find_matches($);
sub find_matches_rec($\@\@);
sub find_word_seq_score(@);
sub get_word_stats($);
sub print_results($@);
sub Usage();

our(%DICT,$TOTAL);
{
  my( $dict_file, $word_file ) = @ARGV;
  ($dict_file && $word_file) or die(Usage);

  {
    my $DICT;
    ($DICT, $TOTAL) = get_word_stats($dict_file);
    %DICT = %$DICT;
  }

  {
    open( my $WORDS, '<', $word_file ) or die "unable to open $word_file\n";

    foreach my $word (<$WORDS>) {
      chomp $word;
      my $arr = find_matches($word);


      local $_;
      # Schwartzian Transform
      my @sorted_arr =
        map  { $_->[0] }
        sort { $b->[1] <=> $a->[1] }
        map  {
          [ $_, find_word_seq_score(@$_) ]
        }
        @$arr;


      print_results( $word, @sorted_arr );
    }

    close $WORDS;
  }
}


sub find_matches($){
    my( $string ) = @_;

    my @found_parses;
    my @words;
    find_matches_rec( $string, @words, @found_parses );

    return  @found_parses if wantarray;
    return \@found_parses;
}

sub find_matches_rec($\@\@){
    my( $string, $words_sofar, $found_parses ) = @_;
    my $length = length $string;

    unless( $length ){
      push @$found_parses, $words_sofar;

      return @$found_parses if wantarray;
      return  $found_parses;
    }

    foreach my $i ( 2..$length ){
      my $prefix = substr($string, 0, $i);
      my $suffix = substr($string, $i, $length-$i);

      if( exists $DICT{$prefix} ){
        my @words = ( @$words_sofar, $prefix );
        find_matches_rec( $suffix, @words, @$found_parses );
      }
    }

    return @$found_parses if wantarray;
    return  $found_parses;
}


## Just a simple joint probability
## assumes independence between words, which is obviously untrue
## that's why this is broken out -- feel free to add better brains
sub find_word_seq_score(@){
    my( @words ) = @_;
    local $_;

    my $score = 1;
    foreach ( @words ){
        $score = $score * $DICT{$_} / $TOTAL;
    }

    return $score;
}

sub get_word_stats($){
    my ($filename) = @_;

    open(my $DICT, '<', $filename) or die "unable to open $filename\n";

    local $/= undef;
    local $_;
    my %dict;
    my $total = 0;

    while ( <$DICT> ){
      foreach ( split(/\b/, $_) ) {
        $dict{$_} += 1;
        $total++;
      }
    }

    close $DICT;

    return (\%dict, $total);
}

sub print_results($@){
    #( 'word', [qw'test one'], [qw'test two'], ... )
    my ($word,  @combos) = @_;
    local $_;
    my $possible = scalar @combos;

    print "$word: $possible possibilities\n";
    foreach (@combos) {
      print ' -  ', join(' ', @$_), "\n";
    }
    print "\n";
}

sub Usage(){
    return "$0 /path/to/dictionary /path/to/your_words";
}
33
ответ дан 8 revs, 2 users 58% 26 November 2019 в 20:11
поделиться

алгоритм Витерби намного быстрее. Это вычисляет те же очки как рекурсивный поиск в ответе Dmitry выше, но в O (n) время. (Поиск Dmitry занимает время; Viterbi делает это динамическим программированием.)

import re
from collections import Counter

def viterbi_segment(text):
    probs, lasts = [1.0], [0]
    for i in range(1, len(text) + 1):
        prob_k, k = max((probs[j] * word_prob(text[j:i]), j)
                        for j in range(max(0, i - max_word_length), i))
        probs.append(prob_k)
        lasts.append(k)
    words = []
    i = len(text)
    while 0 < i:
        words.append(text[lasts[i]:i])
        i = lasts[i]
    words.reverse()
    return words, probs[-1]

def word_prob(word): return dictionary[word] / total
def words(text): return re.findall('[a-z]+', text.lower()) 
dictionary = Counter(words(open('big.txt').read()))
max_word_length = max(map(len, dictionary))
total = float(sum(dictionary.values()))

Тестирование его:

>>> viterbi_segment('wickedweather')
(['wicked', 'weather'], 5.1518198982768158e-10)
>>> ' '.join(viterbi_segment('itseasyformetosplitlongruntogetherblocks')[0])
'its easy for me to split long run together blocks'

, Чтобы быть практичными Вы, вероятно, захотите пару улучшений:

  • Добавляют журналы вероятностей, не умножайте вероятности. Это избегает потери значимости с плавающей точкой.
  • Ваши исходные данные будут в словах общего использования не в Вашем корпусе. Этим подстрокам нужно назначить ненулевая вероятность словами, или Вы заканчиваете без решения или плохого решения. (Это так же верно для вышеупомянутого экспоненциального алгоритма поиска.) Эта вероятность должна быть выкачана от корпусных вероятностей слов и распределена правдоподобно среди всех других кандидатов слова: общая тема известна как сглаживающий в статистических языковых моделях. (Можно сойти с рук некоторые довольно грубые взломы, все же.) Это - то, где O (n) алгоритм Витерби сдувает алгоритм поиска, потому что рассмотрение некорпусных слов аварийно завершает коэффициент ветвления.
74
ответ дан kumardeepakr3 26 November 2019 в 20:11
поделиться

Я думаю, что Вы правы в размышлении, что это не действительно задание для регулярного выражения. Я приблизился бы, это использование идеи словаря - ищут самый длинный префикс, который является словом в словаре. Когда Вы найдете, что, обрубите его и сделайте то же с остатком от строки.

вышеупомянутый метод подвергается неоднозначности, например, "drivereallyfast" сначала нашел бы "драйвер" и затем испытал бы затруднения из-за "eallyfast". Таким образом, необходимо было бы также сделать некоторое отслеживание в обратном порядке при столкновении с этой ситуацией. Или, так как у Вас нет этого многими строками для разделения, просто сделайте вручную тех, которые приводят автоматизированное разделение к сбою.

3
ответ дан Greg Hewgill 26 November 2019 в 20:11
поделиться

Ну, сама проблема не разрешима только с регулярным выражением. Решение (вероятно, не лучшее) состояло бы в том, чтобы получить словарь и сделать соответствие регулярного выражения для каждой работы в словаре к каждому слову в списке, добавив пространство каждый раз, когда успешный. Конечно, это не было бы ужасно быстро, но это будет легко к программе и быстрее, чем рука, делающая его.

1
ответ дан Zoe Gagnon 26 November 2019 в 20:11
поделиться

Основанное на словаре решение требовалось бы. Это могло бы быть упрощено несколько, если у Вас есть ограниченный словарь слов, которые могут произойти, иначе слова, которые формируют префикс других слов, будут проблемой.

1
ответ дан Mitch Wheat 26 November 2019 в 20:11
поделиться

Я могу получить downmodded для этого, но сделали, чтобы секретарь сделал это .

Вы проведете больше времени на решении для словаря, чем оно взяло бы для ручной обработки. Далее, у Вас возможно не будет 100%-й уверенности в решении, таким образом, необходимо будет все еще уделить ему ручное внимание так или иначе.

0
ответ дан Dave Ward 26 November 2019 в 20:11
поделиться

Лучший инструмент для задания здесь является рекурсией, не регулярными выражениями. Основная идея состоит в том, чтобы запуститься с начала строки, ища слово, затем взять остаток от строки и искать другое слово, и так далее пока конец строки не достигнут. Рекурсивное решение является естественным начиная с отслеживания в обратном порядке потребностей произойти, когда данный остаток от строки не может быть поврежден в ряд слов. Решение ниже использует словарь для определения то, что является словом и распечатывает решения, поскольку оно находит их (некоторые строки могут вспыхнуться в несколько возможных наборов слов, например, wickedweather мог быть проанализирован как "злой мы в ней"). Если Вы просто захотите один набор слов, то необходимо будет определить правила для выбора лучшего набора, возможно, путем выбора решения с наименьшим количеством количества слов или путем установки минимальной длины слова.

#!/usr/bin/perl

use strict;

my $WORD_FILE = '/usr/share/dict/words'; #Change as needed
my %words; # Hash of words in dictionary

# Open dictionary, load words into hash
open(WORDS, $WORD_FILE) or die "Failed to open dictionary: $!\n";
while (<WORDS>) {
  chomp;
  $words{lc($_)} = 1;
}
close(WORDS);

# Read one line at a time from stdin, break into words
while (<>) {
  chomp;
  my @words;
  find_words(lc($_));
}

sub find_words {
  # Print every way $string can be parsed into whole words
  my $string = shift;
  my @words = @_;
  my $length = length $string;

  foreach my $i ( 1 .. $length ) {
    my $word = substr $string, 0, $i;
    my $remainder = substr $string, $i, $length - $i;
    # Some dictionaries contain each letter as a word
    next if ($i == 1 && ($word ne "a" && $word ne "i"));

    if (defined($words{$word})) {
      push @words, $word;
      if ($remainder eq "") {
        print join(' ', @words), "\n";
        return;
      } else {
        find_words($remainder, @words);
      }
      pop @words;
    }
  }

  return;
}
8
ответ дан Robert Gamble 26 November 2019 в 20:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: