我正在使用lexical资源文本文件,格式为MULTITEXT v5格式,实际上如下所示:
žvakahžvakatiVme1s0 0.000000
žvakahužvakatiVme3p0 0.000000
žvakalažvakatiVmp-pn 0 0.000000
žvakalažvakatiVmp-sf 45 0.000081
žvakaležvakatiVmp-pf 11 0.000020
žvakaližvakatiVmp-pm 66 0.000119
žvakaložvakatiVmp-sn 10 0.000018
žvakanžvakatiAppmsann0 0.000000
žvakanžvakatiAppmsnn0 0.000000
žvakanžvakatiAppmsvn0 0.000000
格式含义:
[变形词] [引理形式] [语法上下文] ...和我不使用的tf-idf信息
所以,在典型的场景中,我必须匹配〜5000个各种[变形词]以检索[引理形式],更重要的是:[语法上下文] s,其中单个[变形词]实际上可能有更多匹配行(比如žvakan)。搜索的词汇资源大约有7百万行。
到目前为止,我尝试将完整文件加载到List中,然后使用Parallel.ForEach对每行(List项)运行所有~5000 Regex。正则表达式用于灵活地通过[引理形式]查询或仅使用单词的一部分,但为了表现我可以放弃它。花了30分钟才找到大约350个条目。所以,显然我的方法是完全错误的。
现在我正在考虑将完整的文件加载到Dictionary中,其中键是[inflected word](所以我放弃了灵活性)但是我想知道:
Dictionary< [first letter],Dictionary< [inflected word],List< [definition 线] GT;>>
它会做得更好然后加载到:
字典< [inflected word],列表< [定义行]>>
我没有使用ConcurrentDictionary,因为在使用开始之前,内容只被写入数据结构一次。
我的偏好仅仅是查询执行时间 - RAM似乎不是问题 - 使用当前代码我有19Gb的RAM可用,而且我有8个核心CPU,因此对并行执行的任何评论也是受欢迎的。
如果有人想知道:这是一个自然语言处理应用程序。
答案 0 :(得分:1)
我又改变了主意。换上新头。决定最好的方法是递归hashset。当找不到密钥时,需要升级代码以处理异常。我认为这更有效,因为它会自动进行递归。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] inputs = {
"žvakah žvakati Vme1s 0 0.000000",
"žvakahu žvakati Vme3p 0 0.000000",
"žvakala žvakati Vmp-pn 0 0.000000",
"žvakala žvakati Vmp-sf 45 0.000081",
"žvakale žvakati Vmp-pf 11 0.000020",
"žvakali žvakati Vmp-pm 66 0.000119",
"žvakalo žvakati Vmp-sn 10 0.000018",
"žvakan žvakati Appmsann 0 0.000000",
"žvakan žvakati Appmsnn 0 0.000000",
"žvakan žvakati Appmsvn 0 0.000000"
};
LexicalResource resource = new LexicalResource();
foreach (string input in inputs)
{
resource.Add(input);
}
//look up in dictionary
KeyValuePair<int,decimal> lookup = resource.Get("žvakale žvakati Vmp-pf");
}
}
public class LexicalResource
{
public string lexical { get; set; }
public HashSet<LexicalResource> hash { get; set; }
public KeyValuePair<int, decimal> value { get; set; }
public LexicalResource() { }
public void Add(string lexical)
{
string[] tempArray = lexical.Split(new char[] { ' ' });
AddRecursively(this, tempArray);
}
public KeyValuePair<int, decimal> Get(string lexical)
{
string[] tempArray = lexical.Split(new char[] { ' ' });
return GetRecursive(this, tempArray);
}
KeyValuePair<int, decimal> GetRecursive(LexicalResource resource, string[] lexicon)
{
KeyValuePair<int, decimal> results = new KeyValuePair<int, decimal>();
int numberChildren = lexicon.Length;
if (numberChildren == 0)
{
results = resource.value;
}
else
{
LexicalResource child = resource.hash.Where(x => x.lexical == lexicon[0]).FirstOrDefault();
results = GetRecursive(child, lexicon.Skip(1).ToArray());
}
return results;
}
void AddRecursively(LexicalResource resource, string[] lexicon)
{
lexical = lexicon[0];
int numberChildren = lexicon.Length;
if (numberChildren == 2)
{
resource.value = new KeyValuePair<int, decimal>(int.Parse(lexicon[0]), decimal.Parse(lexicon[1]));
}
else
{
if (resource.hash == null)
{
resource.hash = new HashSet<LexicalResource>();
}
LexicalResource child = resource.hash.Where(x => x.lexical == lexicon[0]).FirstOrDefault();
if (child == null)
{
child = new LexicalResource();
resource.hash.Add(child);
}
AddRecursively(child, lexicon.Skip(1).ToArray());
}
}
}
}