Преобразование текста в массив


#1

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

в данный момент я делаю это вручную (var text)


#2

Пример не понял. Можешь входные данные и выходные написать. Если есть какие-то преобразования по шагам, то и их описать.

Но чую, это обычная алгоритмическая задача.


#3

у меня есть фраза “ночная тишина окружала замок из камня и только каменная плита издавала гул”

ее мне нужно разбить на отдельные элементы, однако они формируются не по одному слову: если словосочетание из этой фразы присутствует в массиве, то элемент = этому словосочетанию, если же нет, то это одиночный элемент.

получается что из этой фразы “ночная тишина окружала замок из камня и только каменная плита издавала гул” я должен получить массив как в примере


#4

а как ты словосочетания планируешь выдернуть? :thinking:
Это ж надо анализатор текста писать.


#5

Я понял вашу задачу, но, массивы one и zero чем отличаются?


#6

Держи, написал на онлайн песочнице, так как сейчас под рукой мака нет

let dualWords = ["ночная тишина","каменный замок", "каменная плита","тишина ночи","замок из камня","плита из камня"]

var text = "ночная тишина окружала замок из камня и только каменная плита издавала гул"

var findDualWordsArray = [String]()

for dualWord in dualWords{
    if let rangeFindDualWord =  text.range(of:dualWord){
        //Если находим словосочетания, то заносим их в массив, и удаляем из текста
        findDualWordsArray.append(dualWord)
        text.removeSubrange(rangeFindDualWord)
    }    
}
let resultArrayLastWord = text.components(separatedBy: " ")

let result = resultArrayLastWord + findDualWordsArray
print(result)

//["", "окружала", "", "и", "только", "", "издавала", "гул", "ночная тишина", "каменная плита", "замок из камня"]


#7

Спасибо большое!
пол дня с этим сидел.
массивы отличается битом, в одном случае словосочетание это 1, в другом 0, это нужно для стеганографии, но я могу без проблем создать 3тий массив, а для самой программы использовать эти два. еще раз спасибо, очень помогли!


#8

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


#9

Может так?

let dualWords = ["ночная тишина", "каменный замок", "каменная плита", "тишина ночи", "замок из камня", "плита из камня"]
let text = "ночная тишина окружала замок из камня и только каменная плита издавала гул"

let result = sequence(state: Array(dualWords.compactMap { text.range(of: $0) }.sorted { $0.lowerBound < $1.lowerBound  }.map { (lower: $0.lowerBound, upper: $0.upperBound) }.enumerated())) { items -> [Any]? in
    guard !items.isEmpty else { return nil }
    switch (items.removeFirst(), items.first) {
    case let (current, .some(next)) where current.offset == 0 && text.startIndex < current.element.lower:
        return [(text.startIndex, current.element.lower), Range(uncheckedBounds: current.element), (current.element.upper, next.element.lower)]
    case let (current, .some(next)):
        return [Range(uncheckedBounds: current.element), (current.element.upper, next.element.lower)]
    case let (current, .none):
        return [Range(uncheckedBounds: current.element), (current.element.upper, text.endIndex)]
    }
}.flatMap { $0 }.map { item -> [String] in
    (item as? (String.Index, String.Index)).map { text[$0.0..<$0.1].components(separatedBy: " ").filter { !$0.isEmpty } } ?? [String(text[item as! Range<String.Index>])]
}.flatMap { $0 }

print(result) // ["ночная тишина", "окружала", "замок из камня", "и", "только", "каменная плита", "издавала", "гул"]