目前我有代码,基于CultureInfo cultureInfo = new CultureInfo("ja-JP")
使用
bool found = cultureInfo.CompareInfo.IndexOf(x, y,
CompareOptions.IgnoreCase |
CompareOptions.IgnoreKanaType |
CompareOptions.IgnoreWidth
) >= 0;
由于执行x.IndexOf(y)
的速度更快,我的x
很多且很少更改,我想将x
es规范化一次,并在执行搜索时执行一个简单的
canonicalizedX.indexOf(canonicalize(y));
我的问题:我可以使用.net库中的任何内容,使用我的canonicalize()
和CultureInfo
实现CompareOptions
函数吗?
答案 0 :(得分:1)
你基本上都在问:“.NET是否让我有办法将片假名映射到hirigana,全宽到半宽,这样我就能进行快速比较?”答案是响亮的。你必须自己实现。
这很难。 .NET中的字符串比较由相当广泛的字符比较表驱动。然而,它们被优化用于比较,而不是用于字符替换。通过查看源代码,您可以了解CLR执行此操作的方式。下载SSCLI20发行版并查看clr \ src \ classlibnative \ nls \ sortingtable.cpp源代码文件。 NativeCompareInfo :: LongCompareStringW()函数进行比较,您将看到它使用COMPARE_OPTIONS_IGNOREKANATYPE和COMPARE_OPTIONS_IGNOREWIDTH标志。请注意它如何使用Kana的特殊规则,采取“慢速路径”。这个函数是大量的,你可以从这个反向设计替换算法的几率足够低到零,以便快速提供。日语拼写复杂。
如果你比较的字符串是稳定的,那么考虑存储比较结果并重新使用它。
答案 1 :(得分:0)
我最终使用LCMapStringEx
,它对我来说很好。它不是基于(任意一组)CompareOptions
,而CompareInfo.GetSortKey docs引导我LCMapString
,因此我的indexOf
规范化字符串的效果应该是与CultureInfo.CompareInfo.IndexOf
相同的结果,使用硬编码的CompareOptions
,此处称为dwMapFlags
:
public static string Canonicalize(string src)
{
string localeName = "ja-JP";
string nResult = src;
int nLen, nSize;
uint dwMapFlags = LCMAP_LOWERCASE | LCMAP_HIRAGANA | LCMAP_FULLWIDTH;
IntPtr ptr, pZero = IntPtr.Zero;
nLen = src.Length;
nSize = LCMapStringEx(localeName, dwMapFlags, src, nLen, IntPtr.Zero, 0, pZero, pZero, pZero);
if (nSize > 0)
{
nSize = nSize * sizeof(char);
ptr = Marshal.AllocHGlobal(nSize);
try
{
nSize = LCMapStringEx(localeName, dwMapFlags, src, nLen, ptr, nSize, pZero, pZero, pZero);
if (nSize > 0) nResult = Marshal.PtrToStringUni(ptr, nSize);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
return nResult;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern int LCMapStringEx(
string lpLocaleName,
uint dwMapFlags,
string lpSrcStr,
int cchSrc,
[Out]
IntPtr lpDestStr,
int cchDest,
IntPtr lpVersionInformation,
IntPtr lpReserved,
IntPtr sortHandle);
private const uint LCMAP_LOWERCASE = 0x100;
private const uint LCMAP_UPPERCASE = 0x200;
private const uint LCMAP_SORTKEY = 0x400;
private const uint LCMAP_BYTEREV = 0x800;
private const uint LCMAP_HIRAGANA = 0x100000;
private const uint LCMAP_KATAKANA = 0x200000;
private const uint LCMAP_HALFWIDTH = 0x400000;
private const uint LCMAP_FULLWIDTH = 0x800000;
我也试过了Microsoft.VisualBasic.StrConv,但它的工作速度是LCMapStringEx
的两倍。