Swift 趣味开发:查找拼音首字母全部相同的 4 字成语(中)

在这里插入图片描述

概述

Swift 语言是一门现代化、安全、强大且还算性感的语言。在去年 WWDC 24 中苹果正式推出了秃头码农们期待许久的 Swift 6.0,它进一步完善了 Swift 语言的语法和语义,并再接再厉——强化了现代化并发模型的安全性和灵活性。

在这里插入图片描述

这里我们不妨用 Swift 来验证一个实际世界中有趣的小疑问:汉语中到底有没有拼音首字母全部相同的 4 字成语呢?

到底问题的谜底将会如何?结果绝对会让大家“始料不及”!
那还等什么呢?Let’s go!!!😉


4. 大施拳脚

解决像这种小“鸡”问题无需 Xcode “牛刀”,我们可以将全部测试都放在 Playground 中即可。

首先,我们新建一个 Playground 项目,然后将下载的成语文本文件拖入到其中的 Resources 目录中:

在这里插入图片描述

糟糕,怎么全是乱码!

别急,这是因为 Playground 默认都是以 utf8 编码来打开文本文件,可偏偏这个文件的编码是中文 GB18030。我们会在后面“撸码”打开此文件时再给出解决方案。

5. 字符串的编码

前面提及,这个包含超过 3w 条成语的文本文件实际是由中文 GB18030 来编码的。首先,我们必须在 Playground 中以正确的方式将其打开并转换为字符串:

if let fileUrl = Bundle.main.url(forResource: "all", withExtension: "Txt"), let data = try? Data(contentsOf: fileUrl) {
    
    let encoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.GB_18030_2000.rawValue)))
    
    if let text = String(data: data, encoding: encoding) {
        // 待实现...
    }
}

上面代码的逻辑很清楚,我们尝试打开指定的成语文本文件 “all.Txt”,并将其内容用 GB18030 编码格式转换为字符串(String)。

6. 遍历每条成语

在将海量成语以字符串的形式放到内存之后,我们现在可以来遍历每一条成语的文本了。

经过简单测试发现,每条成语文本是以两对 \r\n 换行符组合来分割的。由此可见,该文件大概率是由 Windows 下的文本编辑器创建的。

这是因为 Windows 和 macOS 的换行符存在显著差异‌。Windows 系统使用“回车(CR)”和“换行(LF)”两个字符序列作为换行符,即 \r\n。而 macOS 则遵循 Unix/Linux标准,使用“换行(LF)”作为换行符,即\n。


有的小伙伴可能会好奇,我是怎么知道每条成语文本实际换行符的?其实很简单,我们让它们自己开口说话。

if let text = String(data: data, encoding: encoding) {
    print(text.prefix(150).debugDescription)
}

代码运行结果如下所示:

" 樽酒论文 拼音:zūn jiǔ lùn wén释义:一边喝酒,一边议论文章。出处:唐·杜甫《春日忆李白》诗何时一樽酒,重与细论文。”示例:连年客里度初度,~第一遭。★陈世宜《上巳社集是日值余初度》诗\r\n\r\n 遵养时晦 拼音:zūn yǎng shí huì释义:遵遵循,按照;时时势;晦隐藏。原为颂"

看到里面隐藏着的换行符了吗?


据此,我们撸起袖子继续完成遍历每条成语的逻辑代码,为了快速调试之目的我们只显示前 10 条成语:

if let fileUrl = Bundle.main.url(forResource: "all", withExtension: "Txt"), let data = try? Data(contentsOf: fileUrl) {
    
    let encoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.GB_18030_2000.rawValue)))
    
    if let text = String(data: data, encoding: encoding) {
        let idiomStrings = text.split(separator: "\r\n\r\n")
        print("共有 \(idiomStrings.count) 条成语")
        
        for (i,string) in idiomStrings.enumerated() {
            guard i < 10 else { break }
            let idiomString = string.trimmingCharacters(in: .whitespacesAndNewlines)
            print("[\(i + 1)]:\(idiomString)")
            // 待实现...
        }
    }
}

在这里插入图片描述

从上图的运行结果可以看到:

  • 该文本文件一共包含 30806 条成语;
  • 前 10 条成语的详细信息;

7. 避繁就简:正则表达式

现在我们已经可以取得每一条成语的详细内容了,接下来就是截取成语名称和对应的拼音了。利用 Swift 中的正则表达式这很好解决。

乐业安居拼音:lè yè ān jū释义:愉快地从事自己的职业,过着安定的生活。形容生活、生产、思想状况安定正常。出处:元·无名氏《延安府》第一折见如今四海无虞,八方黎庶皆丰富,乐业安居。”示例:无

首先,通过观察上面输出成语的具体信息,我们可以得出正则表达式的构建方法:

let idiomNameReg = /(.+?)拼音/
let idiomPinyinReg = /拼音:(.+?)释义/

可以看到,我们根据成语信息中固定“锚点文本”(“拼音”、“释义”)合成了对应成语名称和拼音的正则表达式。

由此,我们可以再接再厉补全后续的代码了:

for (i,string) in idiomStrings.enumerated() {
    guard i < 10 else { break }
    let idiomString = string.trimmingCharacters(in: .whitespacesAndNewlines)
    
    let idiomNameReg = /(.+?)拼音/
    let idiomPinyinReg = /拼音:(.+?)释义/
    if let idiomName = try? idiomNameReg.firstMatch(in: idiomString)?.output.1, let idiomPinyin = try? idiomPinyinReg.firstMatch(in: idiomString)?.output.1 {
        
        let pinyins = idiomPinyin.split(separator: " ")
        print("\(idiomName)(\(idiomPinyin)),拼音个数: \(pinyins.count)")
    }
}

运行代码,我们离最终目标又进了一步:

在这里插入图片描述

但先别高兴的太早!因为上面的逻辑隐藏着一个不为人知的“陷阱”,要知后事如何且听下回分解!


想要进一步系统地学习 Swift 开发的小伙伴们,可以来我的《Swift 语言开发精讲》专栏逛一逛哦:

在这里插入图片描述


总结

在本篇博文中,我们开始了用 Swift 语言实现查找拼音首字母全部相同的 4 字成语的撸码之旅,我们离最后的胜利越来越近了。

感谢观赏,我们下一篇再见!😎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大熊猫侯佩

赏点钱让我买杯可乐好吗 ;)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值