【问题标题】:Efficient way or replacing "a" with "an"?有效的方法还是用“an”替换“a”?
【发布时间】:2020-04-04 16:00:09
【问题描述】:

在我最近的项目中,我正在动态地构建句子,然后通过我的文本以语法上“清理”。我的一个任务是将出现的“a”切换为“an”,其中下一个单词的第一个字母是元音。目前,我只关心小写英文单词,而忽略后面以“h”开头的单词。

我现有的解决方案现在有效,但它看起来非常低效,如果我想在未来支持国际化,肯定无法扩展。

    if ([destination rangeOfString:@" a "].location != NSNotFound) {
        destination = [destination stringByReplacingOccurrencesOfString:@" a a" withString:@" an a"];
        destination = [destination stringByReplacingOccurrencesOfString:@" a e" withString:@" an e"];
        destination = [destination stringByReplacingOccurrencesOfString:@" a i" withString:@" an i"];
        destination = [destination stringByReplacingOccurrencesOfString:@" a o" withString:@" an o"];
        destination = [destination stringByReplacingOccurrencesOfString:@" a u" withString:@" an u"];
    }

我预先检查了“a”的情况,只是为了跳过所有这些替换行的低效率。我在想一定有一种更时尚、更有效的方式来做到这一点,也许是使用正则表达式?

【问题讨论】:

  • 我知道这超出了您的问题范围,但这些类型的数据质量问题通常更适合涉及上游数据源修复的解决方案。
  • 在你走这条路之前,你会想写很多测试用例。当您提高效率时,将很容易破坏功能。请注意,这也会遗漏以 u 开头的异常。 “制服”却是“雨伞”。我很好奇在这种情况下“国际化”意味着什么。请注意,“更时尚”和“更高效”可能不一致。最有效的方法是逐个字符地扫描字符串一次,但可能不像您的意思那样“光滑”。 (同意esqew,你应该专注于在句子结构中解决这个问题。)
  • 状态机扫描解决方案应该非常简单:逐个字符迭代,在“空闲”、“等待一个”(发生在开头和空格之后)、“等待空格”(a 之后),等待“字母”(a 之后的空格),然后如果字母是元音,则发出“an ”,否则发出“a ”。所有其他状态:发出字符。但是你会需要很多测试用例。
  • 同意你的观点,Rob,关于测试用例。是的,我可以看到我将如何一次处理一个字符,并且过去使用传统的 c 字符串做过这种事情。但由于我对 Cocoa 和 Objective-c 比较陌生,我想我可能会缺少一些我尚未遇到的 Foundations 类的功能。

标签: objective-c string nsstring nsregularexpression


【解决方案1】:

在这里可能有用的一个 Foundation 工具是 NSRegularExpression,与您建议的正则表达式行一致。

这是一个例子:

NSString* source = @"What is a apple doing in a toilet? A umbrella is in there too!";

NSRegularExpression *regex = [NSRegularExpression
                              regularExpressionWithPattern:@"\\b([Aa])( [aeiou])"
                              options:0
                              error:nil];
NSString* result = [regex
                     stringByReplacingMatchesInString:source
                     options:0
                     range:NSMakeRange(0, [source length])
                     withTemplate:@"$1n$2"];

几个小笔记:

  • options:0error:nil 条目只是我在实际使用案例中可能有用的选项。
  • 我添加了单词边界 (\\b),以捕捉我想象的可能是“a”的棘手的标点符号后出现(例如“下雨了;出现了一只蚯蚓。”)。 [编辑:哎呀,我错了,那是我想一个“A”开始一个句子的地方。]

希望对你有帮助!

【讨论】:

  • 谢谢科林!这正是我一直在寻找的。正则表达式模式匹配有时可能是一种黑色艺术,这很有帮助。
猜你喜欢
  • 2012-01-19
  • 2020-12-02
  • 2014-09-30
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 2020-09-17
  • 1970-01-01
  • 2011-07-03
相关资源
最近更新 更多