将短语分成不同的单词对

时间:2010-10-29 21:10:07

标签: c# c#-3.0 c#-4.0

我试图弄清楚用什么最好的方法来解析传递给我的单词短语,并根据这些短语构建不同的分组。

示例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

不确定解析此数据的最佳方法是什么。

谢谢,

取值

3 个答案:

答案 0 :(得分:1)

听起来你正在考虑开发grammar。您的排名看起来与parse tree中的令牌深度相同。您的终端符号可以是任何单词,您的起始符号将是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。

我会开始寻找语法解析器。由于它们用于编写编译器,因此有很多这些可用。或者你可以尝试自己编写。无上下文语法实现起来相当简单;你真正需要的只是一个堆栈,一种解释和操作你的语法规则的方法。关于这方面有很多文献,因为它是一个经过深入研究的计算机科学领域。

答案 1 :(得分:1)

你需要一个后缀数组,而不是按字符分隔,用“”标记分隔。 http://en.wikipedia.org/wiki/Suffix_array

Programming Pearls中有一个很好的描述。

答案 2 :(得分:0)

如果我理解你对'等级'的定义,你可以用这样的东西来解决它:

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