I'm trying to figure out why Apple's Natural Language API returns unexpected results.

我做错了什么?这是语法问题吗?

我有以下四个字符串,我想提取每个单词的"stem form"

    // text 1 has two "accredited" in a different order
    let text1: String = "accredit accredited accrediting accredited accreditation accredits"
    
    // text 2 has three "accredited" in different order
    let text2: String = "accredit accredits accredited accrediting accredited accredited accreditation"
    
    // text 3 has "accreditation"
    let text3: String = "accreditation"
    
    // text 4 has "accredited"
    let text4: String = "accredited"

问题在于单词accreditationaccredited.

"accreditation"这个词再也没有出现在词干上.和accredited根据单词在字符串中的顺序返回不同的结果,如附图中的文本1和文本2所示.

enter image description here

我已经用了Apple's documentation的密码

以下是SwiftUI的完整代码:

import SwiftUI
import NaturalLanguage

struct ContentView: View {
    
    // text 1 has two "accredited" in a different order
    let text1: String = "accredit accredited accrediting accredited accreditation accredits"
    
    // text 2 has three "accredited" in a different order
    let text2: String = "accredit accredits accredited accrediting accredited accredited accreditation"
    
    // text 3 has "accreditation"
    let text3: String = "accreditation"
    
    // text 4 has "accredited"
    let text4: String = "accredited"
    
    var body: some View {
        ScrollView {
            VStack {
                
                Text("Text 1").bold()
                tagText(text: text1, scheme: .lemma).padding(.bottom)
                
                Text("Text 2").bold()
                tagText(text: text2, scheme: .lemma).padding(.bottom)
                
                Text("Text 3").bold()
                tagText(text: text3, scheme: .lemma).padding(.bottom)
                
                Text("Text 4").bold()
                tagText(text: text4, scheme: .lemma).padding(.bottom)
                
            }
        }
    }
    
    // MARK: - tagText
    func tagText(text: String, scheme: NLTagScheme) -> some View {
        VStack {
            ForEach(partsOfSpeechTagger(for: text, scheme: scheme)) { word in
                Text(word.description)
            }
        }
    }
    
    // MARK: - partsOfSpeechTagger
    func partsOfSpeechTagger(for text: String, scheme: NLTagScheme) -> [NLPTagResult] {
        
        var listOfTaggedWords: [NLPTagResult] = []
        let tagger = NLTagger(tagSchemes: [scheme])
        tagger.string = text
        
        let range = text.startIndex..<text.endIndex
        let options: NLTagger.Options = [.omitPunctuation, .omitWhitespace]
        
        tagger.enumerateTags(in: range, unit: .word, scheme: scheme, options: options) { tag, tokenRange in
            
            if let tag = tag {
                let word: String = String(text[tokenRange])
                let result = NLPTagResult(word: word, tag: tag)
                
                //if !word.localizedCaseInsensitiveContains(tag.rawValue) {
                listOfTaggedWords.append(result)
                //}
            }
            return true
        }
        
        return listOfTaggedWords
    }
    
    // MARK: - NLPTagResult
    struct NLPTagResult: Identifiable, Equatable, Hashable, Comparable {
        var id = UUID()
        var word: String
        var tag: NLTag?
        
        var description: String {
            var newString: String = "\(word)"
            
            if let tag = tag {
                newString += " : \(tag.rawValue)"
            }
            
            return newString
        }
        
        // MARK: - Equatable & Hashable requirements
        static func == (lhs: Self, rhs: Self) -> Bool {
            lhs.id == rhs.id
        }
        
        func hash(into hasher: inout Hasher) {
            hasher.combine(id)
        }
        
        // MARK: - Comparable requirements
        static func <(lhs: NLPTagResult, rhs: NLPTagResult) -> Bool {
            lhs.id.uuidString < rhs.id.uuidString
        }
    }
    
}

// MARK: - Previews
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

谢谢你的帮助!

推荐答案

至于为什么标记者没有从"认可"中找到"认可",这是因为scheme .lemma找到的是lemma个单词,而不是stems个单词.参见维基百科上的difference between stem and lemma.

词干是单词的一部分,即使在词形变化时也不会改变;引理是这个词的基本形式.例如,从"producted"开始,引理是"product",而茎是"produc-".这是因为在语言分析中有生产和生产这样的词,词干通常被定义为分析的基本形式,所有屈折形式都可以从中形成.

文档中使用了"stem"一词,但我认为引理是本文的目的,而获得"认证"是预期的行为.有关"词干"的更多信息,请参见维基百科文章的Usage节.引理是一个单词的字典形式,"accreditation"有一个字典条目,而"认可"之类的东西则没有.不管你怎么称呼这些东西,关键是有两个不同的概念,标记器会给你其中一个,但你期待着另一个.

至于为什么单词的顺序很重要,这是因为标记者试图将你的单词作为"自然语言"来分析,而不是逐个分析.自然,语序很重要.如果你用.lexicalClass,你会发现它认为text2中的第三个单词是形容词,这就解释了为什么它不认为它的字典形式是"authoridit",因为形容词不是这样共轭的.请注意,accredited在字典中是一个形容词.那么"这是语法问题吗?"确切地

Swift相关问答推荐

解析SON数据的API调用有什么问题?

如何使用变量 Select 哪个向量(?)在我的 struct 中密谋吗?

如何在DATE()中进行比较

NavigationLink和ObservableObject的动画片段

swift:只要框架名称中有一个带有框架名称的公共实体,就指定框架中公共 struct 的路径

将变量设置为 @Published 会 destruct 代码而不会出现任何错误

在扩展中创建通用排序函数

Swift String.firstIndex(of: "\n") 返回 nil,即使字符串有 \n

如何在闭包中使用构造 await sync

列表不显示信息

当使用 CGFloat 而不是数字文字时,为什么 node 的位置会发生变化?

UUID 哈希值是不确定的吗?

try 制作一个 Swift 扩展来替换字符串中的多次出现

iOS SwiftUI - 无法转换 ObservedObject 类型的值

令人满意的 var body:协议扩展中的一些视图

如何让 SwiftUI 中的文本在旋转框架的同时侧向显示?

阻止其他类型的键盘

关闭 UITableViewRowAction

Swift中switch 盒的详尽条件

如何轻松删除领域中的所有对象