如何解决如何将自定义 TokenFilter 从 Lucene.Net 3.0.3 迁移到 4.8
我有以下适用于 Lucene.Net 3.0.3 的自定义 TokenFilter,我需要将其迁移到 Lucene.Net 4.8:
public sealed class AccentFoldingFilter : TokenFilter
{
private ITermAttribute termAttribute;
public AccentFoldingFilter(TokenStream input) : base(input)
{
termAttribute = this.input.GetAttribute<ITermAttribute>();
}
public override bool IncrementToken()
{
if (this.input.IncrementToken())
{
termAttribute.SetTermBuffer(termAttribute.Term.RemoveDiacritics());
return true;
}
return false;
}
}
ITermAttribute
不再存在,我想我需要使用 ICharTermAttribute
但我不知道该怎么做。
如何在 4.8 中做同样的事情?
作为参考,这是 RemoveDiacritics
扩展方法:
public static string RemoveDiacritics(this string text)
{
var normalizedString = text.Normalize(NormalizationForm.FormD);
var stringBuilder = new StringBuilder();
foreach (var c in normalizedString)
{
var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
if (unicodeCategory != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}
解决方法
尽管您可以使用下面的答案,但请注意 Lucene.NET 4.8.0 在框中包含一个 ICUNormalizer2Filter、一个 ICUNormalizer2CharFilter 和一个 ICUFoldingFilter。但是,您可能仍然倾向于使用现有的解决方案,而不是拖入 20MB 以上的依赖项 (ICU4N)。
要翻译,您需要将 ICharTermAttribute
直接添加到过滤器中(而不是在 TokenStream
上)。该属性将通过调用 GetAttribute<ICharTermAttribute>()
从令牌流的共享上下文中拉出。
public sealed class AccentFoldingFilter : TokenFilter
{
private ICharTermAttribute termAttribute;
public AccentFoldingFilter(TokenStream input) : base(input)
{
termAttribute = this.GetAttribute<ICharTermAttribute>();
}
public override bool IncrementToken()
{
if (this.m_input.IncrementToken())
{
string buffer = termAttribute.ToString().RemoveDiacritics();
termAttribute.SetEmpty().Append(buffer);
return true;
}
return false;
}
}
此外,RemoveDiacritics
方法实现没有考虑代理对,这可能导致以后难以诊断错误。
public static string RemoveDiacritics(this string text)
{
var normalizedString = text.Normalize(NormalizationForm.FormD);
int inputLength = normalizedString.Length;
char[] buffer = new char[inputLength];
// TODO: If the strings are short (less than 256 chars),// consider using this (must be unsafe context)
// char* buffer = stackalloc char[inputLength];
int bufferLength = 0;
for (int i = 0; i < inputLength;)
{
// Handle surrogate pairs
int charCount = char.IsHighSurrogate(normalizedString,i)
&& i < inputLength - 1
&& char.IsLowSurrogate(normalizedString,i + 1) ? 2 : 1;
var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(normalizedString,i);
if (unicodeCategory != UnicodeCategory.NonSpacingMark)
{
buffer[bufferLength++] = normalizedString[i]; // high surrogate / BMP char
if (charCount == 2)
{
buffer[bufferLength++] = normalizedString[i + 1]; // low surrogate
}
}
i += charCount;
}
return new string(buffer,bufferLength).Normalize(NormalizationForm.FormC);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。