Как разделить строку как на английский, так и не английский, используя Swift 4? - PullRequest
2 голосов
/ 19 марта 2019

У меня есть строка, которая содержит английский и арабский вместе.Я использую API, поэтому не могу установить в нем индикатор.

Я хочу получить следующее: арабский и английский разделены на две части.Вот пример строки:.

"باسمك ربي وضعت جنبي, وبك أرفعه, فإن أمسكت نفسي فارحمها, وإن أرسلتها فاحفظها, بما تحفظ به عبادك الصالحين Bismika rabbee wadaAAtu janbee wabika arfaAAuh, фа в amsaktanafsee farhamha, wa-in arsaltaha fahfathha bima tahfathu bihi AAibadakas-saliheen. Во имя Твоё, Господь мой, я ложусь, и во Имя Твоё возрождаюсь, поэтому, если Ты возьмешь мою душу, тогда помилуй её, и если Ты вернешь моюзатем защити ее душой так, как Ты поступаешь со своими праведными слугами. ",

Я не могу найти, как разделить его на две части, а арабский и английский я делю на две разные части.

То, что я хочу:

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

Как мне этого достичь?

Ответы [ 3 ]

5 голосов
/ 19 марта 2019

Вы можете использовать Natural Language Tagger , который будет работать, даже если оба сценария смешаны:

import NaturalLanguage

let str = "¿como? بداية start وسط middle начать средний конец نهاية end. 從中間開始. "

let tagger = NLTagger(tagSchemes: [.script])

tagger.string = str

var index = str.startIndex
var dictionary = [String: String]()
var lastScript = "other"


while index < str.endIndex {
    let res = tagger.tag(at: index, unit: .word, scheme: .script)
    let range = res.1

    let script = res.0?.rawValue

    switch script {
    case .some(let s):
        lastScript = s
        dictionary[s, default: ""] += dictionary["other", default: ""] + str[range]
        dictionary.removeValue(forKey: "other")
    default:
        dictionary[lastScript, default: ""] += str[range]
    }

    index = range.upperBound
}

print(dictionary)

и распечатайте результат, если хотите:

for entry in dictionary {
    print(entry.key, ":", entry.value)
}

выход:

Hant : 從中間開始. 
Cyrl : начать средний конец 
Arab : بداية وسط نهاية 
Latn : ¿como? start middle end.

Это все еще не идеально, так как языковой тег проверяет только, к какому сценарию относится наибольшее количество букв в слове . Например, в строке, с которой вы работаете, теггер будет рассматривать الصَّالِحِينَ.Bismika как одно слово. Чтобы преодолеть это, мы могли бы использовать два указателя и обойти исходную строку и проверить скрипт слов индивидуально. Слова определяются как непрерывные буквы :

let str = "بِاسْمِكَ رَبِّي وَضَعْتُ جَنْبِي، وَبِكَ أَرْفَعُهُ، فَإِنْ أَمْسَكْتَ نَفْسِي فَارْحَمْهَا، وَإِنْ أَرْسَلْتَهَا فَاحْفَظْهَا، بِمَا تَحْفَظُ بِهِ عِبَادَكَ الصَّالِحِينَ.Bismika rabbee wadaAAtu janbee wabika arfaAAuh, fa-in amsakta nafsee farhamha, wa-in arsaltaha fahfathha bima tahfathu bihi AAibadakas-saliheen. In Your name my Lord, I lie down and in Your name I rise, so if You should take my soul then have mercy upon it, and if You should return my soul then protect it in the manner You do so with Your righteous servants."

let tagger = NLTagger(tagSchemes: [.script])
var i = str.startIndex
var dictionary = [String: String]()
var lastScript = "glyphs"

while i < str.endIndex {
    var j = i
    while j < str.endIndex,
        CharacterSet.letters.inverted.isSuperset(of: CharacterSet(charactersIn: String(str[j]))) {
        j = str.index(after: j)
    }
    if i != j { dictionary[lastScript, default: ""] += str[i..<j] }
    if j < str.endIndex { i = j } else { break }

    while j < str.endIndex,
        CharacterSet.letters.isSuperset(of: CharacterSet(charactersIn: String(str[j]))) {
        j = str.index(after: j)
    }

    let tempo = String(str[i..<j])
    tagger.string = tempo
    let res = tagger.tag(at: tempo.startIndex, unit: .word, scheme: .script)

    if let s = res.0?.rawValue {
        lastScript = s
        dictionary[s, default: ""] += dictionary["glyphs", default: ""] + tempo
        dictionary.removeValue(forKey: "glyphs")
    }
    else { dictionary["other", default: ""] += tempo }

    i = j
}
4 голосов
/ 19 марта 2019

Шаг 1: Вы должны разбить всю строку на массив с помощью "."как я вижу, есть "."между предложениями.

Шаг 2: Пропустите каждое предложение, чтобы определить его язык, и добавьте в другую строку.

Окончательный код

//add in your viewController

enum Language : String {
case arabic = "ar"
case english = "en"
}

override func viewDidLoad() {
    super.viewDidLoad()
    //make array of string
    let kalmaArray = "بِاسْمِكَ رَبِّي وَضَعْتُ جَنْبِي، وَبِكَ أَرْفَعُهُ، فَإِنْ أَمْسَكْتَ نَفْسِي فَارْحَمْهَا، وَإِنْ أَرْسَلْتَهَا فَاحْفَظْهَا، بِمَا تَحْفَظُ بِهِ عِبَادَكَ الصَّالِحِينَ.Bismika rabbee wadaAAtu janbee wabika arfaAAuh, fa-in amsakta nafsee farhamha, wa-in arsaltaha fahfathha bima tahfathu bihi AAibadakas-saliheen. In Your name my Lord, I lie down and in Your name I rise, so if You should take my soul then have mercy upon it, and if You should return my soul then protect it in the manner You do so with Your righteous servants.".components(separatedBy: ".")

    splitInLanguages(kalmaArray: kalmaArray)

}



private func splitInLanguages(kalmaArray: [String]){
    var englishText = ""
    var arabicText = ""

    for kalma in kalmaArray {

        if kalma.count > 0 {

            if let language = NSLinguisticTagger.dominantLanguage(for: kalma) {
                switch language {
                case Language.arabic.rawValue:
                    arabicText.append(kalma)
                    arabicText.append(".")
                    break
                default: // English
                    englishText.append(kalma)
                    englishText.append(".")
                    break
                }
            } else {
                print("Unknown language")
            }
        }
    }

    debugPrint("Arabic: ", arabicText)
    debugPrint("English: ", englishText)
}

Надеюсь, это поможет вам разбить строку на два языка.Дайте мне знать, если у вас все еще есть проблемы.

1 голос
/ 19 марта 2019

Вы можете использовать NaturalLanguageTagger в ответе @ielyamani, но единственным ограничением является то, что это iOS 12+

Если вы пытаетесь сделать это на более ранних версиях iOS, вы можете взглянуть на NSCharacterSet

Вы можете создать свой собственный characterset, чтобы проверить, есть ли в строке английские символы и цифры

extension String {

     func containsLatinCharacters() -> Bool {

        var charSet = NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
        charSet = charSet.invertedSet

        let range = (self as NSString).rangeOfCharacterFromSet(charSet)

        if range.location != NSNotFound {
            return false
        }

        return true
    }
}

Другой вариант - использовать уже имеющиеся наборы символов:

let nonLatinString = string.trimmingCharacters(in: .alphanumerics)//symbols will still get through
let latinString = string.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)//symbols and non-latin characters wont get through

С их помощью вы можете легко получить нужные вам строки. Но если они недостаточно хороши, вы можете создать свой собственный набор символов, использовать union, intersect и т. Д., Чтобы отфильтровать требуемые и нежелательные символы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...