在 Swift 中将文本限制为一定数量的单词

Posted

技术标签:

【中文标题】在 Swift 中将文本限制为一定数量的单词【英文标题】:Limit text to a certain number of words in Swift 【发布时间】:2021-09-30 12:54:42 【问题描述】:

在移动应用程序中,我使用的 API 只能处理大约 300 个单词。如何在 Swift 中修剪字符串以使其不包含更多单词?

原生 .trimmingCharacters(in: CharacterSet) 似乎无法做到这一点,因为它旨在修剪某些字符。

【问题讨论】:

单词或字符?对于字符,你可以使用prefix(_:)developer.apple.com/documentation/swift/string/2894830-prefix,对于单词,你可能要数(单词的数量,用什么分隔?空格)?然后,调用prefix(_:),重新组合你的字符串。 【参考方案1】:

没有现成的方法来限制字符串中的单词数。

如果您查看this post,它使用enumerateSubstrings(in: Range) 方法记录并设置.byWords 选项。看起来它返回了一个 Range 值的数组。

您可以使用它在 String 上创建一个扩展,该扩展将返回该字符串的前 X 个单词:

extension String 
    func firstXWords(_ wordCount: Int) -> Substring 
        var ranges: [Range<String.Index>] = []
        self.enumerateSubstrings(in: self.startIndex..., options: .byWords)  _, range, _, _ in
            ranges.append(range)
        
        if ranges.count > wordCount - 1 
            return self[self.startIndex..<ranges[wordCount - 1].upperBound]
         else 
            return self[self.startIndex..<self.endIndex]
        
    

如果我们再运行代码:

let sentence = "I want to an algorithm that could help find out how many words are there in a string separated by space or comma or some character. And then append each word separated by a character to an array which could be added up later I'm making an average calculator so I want the total count of data and then add up all the words. By words I mean the numbers separated by a character, preferably space Thanks in advance"

print(sentence.firstXWords(10))

输出是:

我想要一个可以帮助找出答案的算法

使用enumerateSubstrings(in: Range) 将比使用空格分割字符串提供更好的结果,因为在普通文本(换行符、逗号、冒号、em 空格等)中除了空格之外还有更多的分隔符。适用于日语和中文等单词之间通常没有空格的语言。

您可以重写函数以在字符串达到所需字数时立即终止枚举。如果您想要一个非常长的字符串中的一小部分单词,这会使其显着更快(上面的代码应该具有O(n)的性能,尽管我没有深入挖掘以确保那个。我也想不出如何提前终止enumerateSubstrings()函数,虽然我没有那么努力。)

Leo Dabus 提供了我的函数的改进版本。它扩展了 StringProtocol 而不是 String,这意味着它可以处理子字符串。另外,一旦达到您想要的字数,它就会停止,因此查找很长字符串的前几个单词会更快:

extension StringProtocol 
    func firstXWords(_ n: Int) -> SubSequence 
        var endIndex = self.endIndex
        var words = 0
        enumerateSubstrings(in: startIndex..., options: .byWords)  _, range, _, stop in
            words += 1
            if words == n 
                stop = true
                endIndex = range.upperBound
            
        
        return self[..<endIndex] 

【讨论】:

您使用的是句子 startIndex 而不是字符串索引。请注意,一旦达到所需的单词数,就无需继续枚举单词。您可以简单地将您忽略的停止(第 4 个)参数设置为 true。您还应该扩展 StringProtocol 以支持子字符串 extension StringProtocol 987654331 var endIndex = self.endIndex 987654333 enumerateSubstrings(in: startIndex..., options: .byWords) _, range, _, stop in 987654335 if words == n 987654337 endIndex = range.upperBound 987654339 987654341 987654343 @ Leo,感谢您的反馈。我认为有一种方法可以终止评估,但这是一个快速的答案,我没有深入挖掘。我也无法弄清楚如何返回 StringProtocol 而不是 String。扩展 StringProtocol 是有意义的。您要提交自己的答案吗? 很好地了解使用 sentence.startIndex。 (已修复)。)我开始编写一次性代码,并没有足够仔细地审查编辑以将其转换为扩展。 哦,没关系。我尝试使用您的版本,但有一个错字。

以上是关于在 Swift 中将文本限制为一定数量的单词的主要内容,如果未能解决你的问题,请参考以下文章

如何在独立的火花中将处理限制为指定数量的核心

java - 如何在java中将特定数量的线程限制为同步块

php 将帖子摘录限制为固定数量的单词

php 将帖子摘录限制为固定数量的单词

php 将帖子摘录限制为固定数量的单词

如何限制 Swift 中文本字段中的数字?