Разбор строки в объект в Swift - PullRequest
0 голосов
/ 21 ноября 2018

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

[
id=2997,rapidViewId=62,state=ACTIVE,name=Sprint7,startDate=2018-11-20T10:28:37.256Z,endDate=2018-11-30T10:28:00.000Z,completeDate=<null>,sequence=2992,goal=none
]

Как мнепреобразовать его красиво в хорошо сформированный быстрый объект самым простым способом?

Вот моя попытка, которая дает мне только значение Sprint

if sprintJiraCustomField.count > 0 {
                         let stringOutput = sprintJiraCustomField.first?.stringValue // convert output to String
                        let name = stringOutput?.components(separatedBy: "name=") // get name section from string
                        let nameFieldRaw = name![1].components(separatedBy: ",") // split out to the comma
                        let nameValue = nameFieldRaw.first!
                        sprintDetail = nameValue// show name field
                        }

Ответы [ 3 ]

0 голосов
/ 21 ноября 2018

Это работа для сокращения:

let keyValueStrings = yourString.components(separatedBy: ",")

let dictionary = keyValueStrings.reduce([String: String]()) {
    (var aggregate: [String: String], element: String) -> [String: String] in

    let elements = element.componentsSeparatedByString("=")
    let key = elements[0]

    // replace nil with the value you want to use if there is no value        
    let value = (elements.count > 1) ? elements[1] : nil
    aggregate[key] = value

    return aggregate
}

Это функциональный подход, но вы можете добиться того же, используя для итерации.Так что тогда вы можете использовать основной способ отображения Swift.например, у вас будет собственная структура объекта.Сначала вы добавите к нему метод init.Затем сопоставьте ваш объект так:

init(with dictionary: [String: Any]?) {
  guard let dictionary = dictionary else { return }
  attribute = dictionary["attrName"] as? String
}

let customObjec = CustomStruct(dictionary: dictionary)
0 голосов
/ 21 ноября 2018

У нас уже есть предложение сначала разбить строку на каждую запятую, а затем разбить каждую часть на знак равенства.Это довольно просто кодировать и работает хорошо, но это не очень эффективно, так как каждый символ должен проверяться несколько раз.Написание правильного парсера с использованием Scanner так же просто, но будет работать быстрее.

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

При этом алгоритм будет иметь следующие шаги:

  1. Создать сканер со строкой ввода
  2. Проверить открывающую скобку, в противном случае произойдет сбой
  3. Сканирование до первого =.Это ключ
  4. Использовать =
  5. Сканирование до первого , или ].Это значение
  6. Сохраните пару ключ / значение
  7. Если есть ,, используйте его и продолжайте с шага 3
  8. Потребьте окончательный ].

К сожалению, API Scanner не очень удобен для Swift.С небольшим расширением его гораздо проще использовать:

extension Scanner {
    func scanString(_ string: String) -> Bool {
        return scanString(string, into: nil)
    }

    func scanUpTo(_ delimiter: String) -> String? {
        var result: NSString? = nil
        guard scanUpTo(delimiter, into: &result) else { return nil }
        return result as String?
    }

    func scanUpTo(_ characters: CharacterSet) -> String? {
        var result: NSString? = nil
        guard scanUpToCharacters(from: characters, into: &result) else { return nil }
        return result as String?
    }
}

С этим мы можем написать функцию разбора следующим образом:

func parse(_ list: String) -> [String: String]? {
    let scanner = Scanner(string: list)

    guard scanner.scanString("[") else { return nil }

    var result: [String: String] = [:]

    let endOfPair: CharacterSet = [",", "]"]
    repeat {
        guard
            let key = scanner.scanUpTo("="),
            scanner.scanString("="),
            let value = scanner.scanUpTo(endOfPair)
        else {
            return nil
        }

        result[key] = value
    } while scanner.scanString(",")

    guard scanner.scanString("]") else { return nil }

    return result
}
0 голосов
/ 21 ноября 2018

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

let items = stringOutput.components(separatedBy: ",").compactMap( {pair -> (String, String) in
    let keyValue = pair.components(separatedBy: "=")
    return (keyValue[0], keyValue[1])
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...