Разберите фразы в разные пары слов - PullRequest
0 голосов
/ 30 октября 2010

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

Пример XML:

<root>
   <keyword value=""My First Phrase""/>
   <keyword value=""My First Phrase Again""/>
   <keyword value=""My First Phrase Again and Again""/>
</root>

Так что я бы извлек их из xml:

My First Phrase
My First Phrase Again
My First Phrase Again and Again

Затем я хотел бы построить эти новые фразы из оригинала:

My First Phrase   
My First
First Phrase
My
First
Phrase

My First Phrase Again
My First Phrase
First Phrase Again
My First
First Phrase
Phrase Again
My
First
Phrase
Again

Это позволило бы мне разбить фразы и выстроить своего рода ранжирование из этих слов.Я создал несколько списков и перебрал их, но это не так, как я ожидал.

Итак, для ранжирования я имею в виду следующее:

My First Phrase Again    Rank: 1 (Exact Match)
My First Phrase          Rank: 2
First Phrase Again       Rank: 2
My First                 Rank: 3
First Phrase             Rank: 3
Phrase Again             Rank: 3
My                       Rank: 4
First                    Rank: 4
Phrase                   Rank: 4
Again                    Rank: 4

Не уверен, что наилучший подход будет для анализа этих данных.

Спасибо,

S

Ответы [ 3 ]

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

Вам нужен массив суффиксов, но вместо разделения по символам, разделенных токеном "".http://en.wikipedia.org/wiki/Suffix_array

Это хорошее описание есть в Programming Pearls .

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

Звучит так, будто вы разрабатываете грамматику . Ваши рейтинги выглядят так же, как и глубина их токенов в дереве разбора . Символами вашего терминала будут любые слова, а начальными символами будут предложения, перечисленные в вашем элементе root.

Например:

S -> X Y
X -> M F
Y -> P A
M -> "My"
F -> "First"
P -> "Phrase"
A -> "Again"

В этом случае глубина «My First Phrase Again» будет равна 0 в дереве разбора, глубина «My First» и «Phrase Again» будет 1, а глубина «My», «First» "," Фраза "и" Снова "будет 2.

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

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

Если я правильно понимаю ваше определение «ранга», вы можете решить его следующим образом:

public class PhraseRanking : IEnumerable<KeyValuePair<string, int>>
{
    private readonly Dictionary<string, int> _ranking;

    public PhraseRanking()
    {
        _ranking = new Dictionary<string, int>();
    }

    public PhraseRanking(string phrase)
        : this()
    {
        var words = phrase.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        var sb = new StringBuilder(phrase.Length);
        for(int i = words.Length; i > 0; --i)
        {
            int rank = words.Length - i + 1;
            int lastFirstWordIndex = words.Length - i;
            for(int j = 0; j <= lastFirstWordIndex; ++j)
            {
                sb.Clear();
                int lastWordIndex = j + i - 1;
                for(int k = j; k <= lastWordIndex; ++k)
                {
                    sb.Append(words[k]);
                    if(k != lastWordIndex) sb.Append(' ');
                }
                _ranking[sb.ToString()] = rank;
            }
        }
    }

    public int this[string phrase]
    {
        get { return _ranking[phrase]; }
    }

    public int Count
    {
        get { return _ranking.Count; }
    }

    public IEnumerator<KeyValuePair<string, int>> GetEnumerator()
    {
        return _ranking.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return _ranking.GetEnumerator();
    }
}

Использование:

var ranking = new PhraseRanking("My First Phrase Again");
var sb = new StringBuilder();
foreach(var rank in ranking)
{
    sb.AppendLine(rank.Value.ToString() + ": " + rank.Key);
}
MessageBox.Show(sb.ToString());

Вывод:

1: My First Phrase Again
2: My First Phrase
2: First Phrase Again
3: My First
3: First Phrase
3: Phrase Again
4: My
4: First
4: Phrase
4: Again
...