Как убедиться, что строка содержит все слово, а не его часть - PullRequest
0 голосов
/ 05 августа 2020

Мне нужен некоторый код, чтобы убедиться, что если в текстовом файле с форматированием возврата есть целое слово, оно принимается и что, если присутствует только его часть, оно не рассматривается. lau в TextField это принято, и я бы предпочел, чтобы ответ был ложным, пока не будет найдено все слово

Вот файл limited.txt, который я использую в своем проекте. Каждое слово находится в отдельной строке: аппетит аппетитность аппетит аппетит аппетит аппетит аппетит аплодисменты аплодисменты аплодисменты аплодисменты аплодисменты аплодисменты аплодисменты аплодисменты аплодисменты аплодисменты аплодисменты яблоко аплодисменты яблоко аплодисменты яблоко аплодисменты

Спасибо за вашу помощь

import SwiftUI

struct ContentView: View{
    @ObservedObject var textFileStringContent: TexFileReader
    @State private var text = ""

    var body: some View{
        VStack {
            TextField("please type the word to check", text: $text)
            // so that it does not matter if user capitalises a word
            if textFileStringContent.data.contains(self.text.lowercased()) {
                Text("part of it exists")
                
                // I tried to code it in here but to no avail
                // if it is a whole word {
                // Text("congratulations it does exist")
                // }
                
            } else if !text.isEmpty {
                Text("sorry no such word")
            }
        }.padding().font(.headline)
            .navigationBarTitle("Word checker")
    }
}

class TexFileReader: ObservableObject {
    @Published var data: String = ""
    
    init() { self.load(file: "limited") }
    func load(file: String) {
        if let filepath = Bundle.main.path(forResource: file, ofType: "txt") {
            do {
                let contents = try String(contentsOfFile: filepath)
                DispatchQueue.main.async {
                    self.data = contents
                    
                     print(self.data.contains("lau"))
                    // this prints true even if lau is not a whole word
                    // applaud
                    // applaudable
                    // applaudably
                    // applauded
                    // applauder
                    // applauders
                    // applauding
                    // applaudingly
                    // applauds
                    // applause
                    // applauses
                    // applausive
                    // applausively
                    // but present in each of these
                    // I need to make sure that the match is a whole word not just part of one
                   
                    
                }
            } catch let error as NSError {
                print(error.localizedDescription)
            }
        } else {
            print("File not found")
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 05 августа 2020

Возможный способ - поиск с использованием регулярного выражения и спецификатора границы слова \\b

if textFileStringContent.data.range(of: "\\b\(self.text)\\b", options: [.caseInsensitive, .regularExpression]) != nil {
0 голосов
/ 05 августа 2020

Foundation содержит механизм анализа языка NSLinguisticTagger, который может делать много вещей, включая поиск определенных c слов с учетом языкового стандарта.

Простая реализация того, что вы пытаетесь сделать:

//extension via https://stackoverflow.com/questions/15062458/shortcut-to-generate-an-nsrange-for-entire-length-of-nsstring/56391610#56391610
extension String {
    func range(from nsRange: NSRange) -> Range<String.Index>? {
        return Range(nsRange, in: self)
    }
}

var tagger = NSLinguisticTagger(tagSchemes: [NSLinguisticTagScheme.tokenType], options: 0)

let baddata = """
applaud
applaudable
applaudably
applauded
applauder
applauders catlau
applauding
"""

let gooddata = """
applaud
applaudable
applaudably
applauded
applauder
applauders lau catlau
applauding
"""

var foundLau = false
tagger.string = baddata
tagger.enumerateTags(in: NSRange(location: 0, length: baddata.count), scheme: .tokenType, options: [.omitWhitespace]) { tag, tokenRange, _, _ in
    if tag != nil, let range = baddata.range(from: tokenRange) {
        let fragment = baddata[range]
        if fragment.lowercased() == "lau" {
            foundLau = true
        }
    }
}

print("found \"lau\" in baddata =", foundLau ? "true":"false")

tagger.string = gooddata
tagger.enumerateTags(in: NSRange(location: 0, length: gooddata.count), scheme: .tokenType, options: [.omitWhitespace]) { tag, tokenRange, _, _ in
    if tag != nil, let range = gooddata.range(from: tokenRange) {
        let fragment = gooddata[range]
        if fragment.lowercased() == "lau" {
            foundLau = true
        }
    }
}

print("found \"lau\" in gooddata =", foundLau ? "true":"false")

enumerateTags возвращает NSRange, которое может быть преобразовано в Range для общего использования Swift.

0 голосов
/ 05 августа 2020

Вы можете проверить, заканчивается ли он разделителем новой строки в текстовом файле:

let textWithNewline = self.text.lowercased() + "\n"
if textFileStringContent.data.contains(textWithNewline) {
    // it is a whole word
}
...