字符串解析和匹配算法
作者:互联网
我正在解决以下问题:
假设我有一个软件包列表,它们的名称可能看起来像这样(唯一已知的是,这些名称的格式类似于SOMETHING VERSION,这意味着该版本始终位于名称之后):
Efficient.Exclusive.Zip.Archiver-PROPER.v.122.24-EXTENDED
Efficient.Exclusive.Zip.Archiver.123.01
Efficient-Exclusive.Zip.Archiver(2011)-126.24-X
Zip.Archiver14.06
Zip-Archiver.v15.08-T
Custom.Zip.Archiver1.08
Custom.Zip.Archiver1
现在,我需要解析此列表,并仅选择每个软件包的最新版本.对于此示例,预期结果将是:
Efficient-Exclusive.Zip.Archiver(2011)-126.24-X
Zip-Archiver.v15.08-T
Custom.Zip.Archiver1.08
我使用的当前方法可以通过以下方式描述:
Split the initial strings into groups by their starting letter,
ignoring spaces, case and special symbols.
(`E`, `Z`, `C` for the example list above)
Foreach element {
Apply the regular expression (or a set of regular expressions),
which tries to deduce the version from the string and perform
the following conversion `STRING -> (VERSION, STRING_BEFORE_VERSION)`
// Example for this step:
// 'Efficient.Exclusive.Zip.Archiver-PROPER.v.122.24-EXTENDED' ->
// (122.24, Efficient.Exclusive.Zip.Archiver-PROPER)
Search through the corresponding group (in this example - the 'E' group)
and find every other strings, which starts from the 'STRING_BEFORE_VERSION' or
from it's significant part. This comparison is performed in ignore-case and
ignore-special-symbols mode.
// The matches for this step:
// Efficient.Exclusive.Zip.Archiver-PROPER, {122.24}
// Efficient.Exclusive.Zip.Archiver, {123.01}
// Efficient-Exclusive.Zip.Archiver, {126.24, 2011}
// The last one will get picked, because year is ignored.
Get the possible version from each match, ***pick the latest, yield that match.***
Remove every possible match (including the initial element) from the list.
}
该算法(我假设)应该适用于O(N * V N lg N * M),其中M表示平均字符串匹配时间,V表示版本正则表达式工作时间.
但是,我怀疑有更好的解决方案(总是存在!),也许是特定的数据结构或更好的匹配方法.
如果您可以对当前方法提出建议或做一些注释,请不要犹豫.
解决方法:
这个怎么样? (伪代码)
Dictionary<string,string> latestPackages=new Dictionary<string,string>(packageNameComparer);
foreach element
{
(package,version)=applyRegex(element);
if(!latestPackages.ContainsKey(package) || isNewer)
{
latestPackages[package]=version;
}
}
//print out latestPackages
字典操作为O(1),因此您的运行时总数为O(n).无需预先分组,而不是存储所有匹配项,而仅存储当前最新的匹配项.
字典具有一个接受IEqualityComparer对象的构造函数.在那里,您可以实现自己的包名称之间相等的语义.但是请记住,您需要在此IEqualityComparer中实现GetHashCode方法,该方法应为您认为相等的对象返回相同的值.要重现上面的示例,您可以返回字符串中第一个字符的哈希码,这将重现您词典中的分组.但是,使用更智能的哈希代码(不会有太多冲突),您将获得更高的性能.如果仍能产生良好的效果,则可能使用更多字符.
标签:string-matching,version,string,c,algorithm 来源: https://codeday.me/bug/20191201/2083625.html