Я использую swiftyjson, чтобы возиться с моими данными json.
В настоящее время я получаю данные, значения которых я хочу объединить. (это станет более понятным, если вы посмотрите на пример ниже. Я пробовал много разных подходов, таких как использование цикла for для просмотра данных JSON, но он все дублирует. Я также попытался изменить свой json на 2d массив, затем фильтруя его, но похоже, что это все усложняет. Должен быть более простой способ ...
var jsondata = {
{
fruit: "APPLE"
amount: 10
},{
fruit: "Mango"
amount: 5
},{
fruit: "APPLE"
amount: 5
},{
fruit: "Mango"
amount: 5
},{
fruit: "orange"
amount: 500
}
}
var NEWjsondata =
{
{
fruit: "APPLE"
amount: 15
},
{
fruit: "Mango"
amount: 10
},
{
fruit: "orange"
amount: 500
}
}
Мой подход
var arr = ["Apple","Mango","Orange"]
for (key,json) in jsondata {
arr.append(json["fruit"])
if arr.contains(json["fruit"]){
json["amount"] = json["amount"] + json["amount"]
}}
@ Цель, это помощник в псевдокоде:]
покажите код, который вы пробовали. создать новый словарь, который может поддерживать тип элемента в массиве, а затем выполнить итерацию по массиву, если «фрукт» уже есть, добавить сумму, если не добавить фрукт и количество.
@Scriptable обновил пост с моим подходом. Проблема с вашим предложением заключается в том, что это приведет к добавлению повторяющихся записей. Это был первый подход, который я применил.
нет, если вы сначала проверите наличие плодов.
@Scriptable Я. Я добавляю переменную arr по мере того, как я просматриваю файл json в цикле for. Взгляните на мое обновление. Я проверяю, содержит ли уже следующий фрукт



Я просматриваю все словари и извлекаю из каждого фрукта название и количество, а затем делаю новую запись в словаре результатов или добавляю к уже подсчитанному ранее количеству.
func mergedDict(dictionaries: [[String: Any]]) -> [String: Int] {
guard dictionaries.count != 0 else { return [:] }
var result = [String: Int]()
dictionaries.forEach { dict in
var name: String?
var amount: Int?
dict.forEach{ arg in
switch arg.key {
case "fruit":
name = arg.value as! String
case "amount":
amount = arg.value as! Int
default:
fatalError("does not exist.")
}
}
guard let fruit = name else { fatalError("name is nil.") }
guard let newAmount = amount else { fatalError("amount is nil.") }
guard let priorAmount = result[fruit] else {
result[fruit] = newAmount
return
}
result[fruit] = priorAmount + newAmount
}
return result
}
Приведение FruitStruct в соответствие с протоколом Codable позволяет encoder.encode принимать наш массив FruitStruct. Структура имитирует JSON, который мы хотим. Можно добавить enum CodingKeys, чтобы изменить отображение структуры на фактический JSON.
struct FruitStruct: Codable {
let fruit: String
let amount: Int
}
func json(fromDict: [String: Int]) throws -> String {
let fruitStructs = fromDict.map { arg in
return FruitStruct(fruit: arg.key, amount: arg.value)
}
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(fruitStructs)
guard let string = String(data: data, encoding: .utf8) else {
fatalError("failed to decode json-Data to String with utf8.")
}
return string
}
@iloveStackOverflow. Вы можете создать struct FruitStruct { let fruit: String; let amount: Int}, сопоставить mergedDict с [FruitStruct] и закодировать его с помощью JSONEncoder. Сможете ли вы это сделать или вам нужно больше рекомендаций?
Кстати ... в JSONEncoder есть параметр .prettyPrint.
Ничего, я разберусь. Еще раз, спасибо :]
на самом деле да, мне нужно больше рекомендаций относительно структуры фруктов. Пытался сам, но не могу заставить его работать.
@iloveStackOverflow Для этого вы должны прочитать о Encodable, CodingKeys и функции карты. Вы должны знать .filter, .map, .sorted, .enumerated, .forEach наизусть, так что читайте и о них. Они делают жизнь намного проще. Map использует универсальные шаблоны, чтобы попытаться определить тип вывода. Обновил пост.
Нормально будет сделать. И я предполагаю, что "toJson" должен принимать параметр [[String: Int]], а не [String: Int], поскольку я буду передавать в него результат возврата от mergeDict.
@iloveStackOverflow Я думаю, что у вас все не так, но да, вывод mergedDict переходит в toJSON. Не забывай заглядывать в темы, а то мне будет грустно. ;)
Это недействительные данные JSON. Здесь вы можете увидеть, действителен ли он.