Быстрое группирование по ключу во вложенном словаре - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть следующий json, который я пытаюсь сгруппировать, используя функцию swift.

{
  "response": [
    {
      "user": "A",
      "details": {
        "source": "Tab"
      }
    },
    {
      "user": "B",
      "details": {
        "source": "Tab"
      }
    },
    {
      "user": "C",
      "details": {
        "source": "Desktop"
      }
    },
    {
      "user": "D",
      "details": {
        "source": "Mobile"
      }
    }
  ]
}

Итак, я попробовал группировать по ключу «детали», но он не позволит мне добавить ключ источника в методе группировки.

let groupedDict = Словарь (группировка: элементы, по: {$ 0 ["устройство"] как! [String: String]})

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

Вывод, который я пытаюсь достичь, следующий:

{
  "Mobile": [
    {
      "user": "C",
      "details": {
        "source": "Mobile"
      }
    }
  ],
  "tab": [
    {
      "user": "A",
      "details": {
        "source": "Tab"
      }
    },
    {
      "user": "B",
      "details": {
        "source": "Tab"
      }
    }
  ],
  "Desktop": [
    {
      "user": "C",
      "details": {
        "source": "Desktop"
      }
    }
  ]
}

Любые выводы приветствуются. ТИА

Edit:

Чтобы можно было отфильтровать его в определенном порядке. т.е. Mobile, Tab и Desktop, как показано в ответе.

Ответы [ 2 ]

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

Выполните три шага

  1. Найдите уникальные значения ключа "source"
  2. Уникальный ключ GroupBy и создайте словарь
  3. Преобразуйте словарь вJson

Вот код

let response = jsonResult["response"] as! [[String :Any]]

Найти уникальные значения ключа «источника»

let array = (response).map { ($0["details"] as! [String:Any])["source"] as! String }
let uniqueSourceKeyArray = Set.init(array)

GroupBy уникальный ключ и сделатьСловарь

var dictTemp = [String:Any]()
for obj in uniqueSourceKeyArray {
let dict = (response).filter({($0["details"] as! [String:Any])["source"] as! String == obj })
  dictTemp[obj] = dict
}

Преобразование словаря в Json

if let jsonResult1 = try JSONSerialization.data(withJSONObject: dictTemp, options: []) as?  Data {
  let finalJson = String.init(data: jsonResult1, encoding: .utf8)
  print(finalJson!)
}

Результат

{"Tab":[{"user":"A","details":{"source":"Tab"}},{"user":"B","details":{"source":"Tab"}}],"Mobile":[{"user":"D","details":{"source":"Mobile"}}],"Desktop":[{"user":"C","details":{"source":"Desktop"}}]}
0 голосов
/ 13 ноября 2018

Я достиг этого,

1 - Decode ответом на Object.

2 - фильтрацией 3 arrays каждого типа.

3 - сгруппированы эти массивы.

Соблюдайте приведенный ниже код.

struct MyObject: Codable {
    var response: [DataBody]
    struct DataBody: Codable {
        var user: String
        var details: Details
    }
    struct Details: Codable {
        var source: String
    }
}

let myObject = try? JSONDecoder().decode(MyObject.self, from: jsonData!)
let tabs = myObject!.response.filter({$0.details.source == "Tab"})
let desktops = myObject!.response.filter({$0.details.source == "Desktop"})
let mobiles =  myObject!.response.filter({$0.details.source == "Mobile"})

var grouped = Dictionary(grouping: myObject!.response, by: { $0.details.source })
[
    "Tab": tabs,
    "Desktop": desktops ,
    "Mobile": mobiles
]

Это делается с помощью Swift4

Мы еще не закончили, до 100% проверки результата

1- encodeгруппироваться.

2 - преобразовать его в String

3 - печать.

Проверьте это.

let encdoedData = try!  JSONEncoder().encode(grouped)

let finalResult = String(data: encdoedData, encoding: .utf8)

print(finalResult!)

Результат:

{"Tab": [{"details": {"source": "Tab"}, "user": "А"}, { "детали": { "источник": "Tab"}, "пользователь": "B"}], "Рабочий стол": [{ "детали": { "источник": "Рабочий стол"}, "user": "C"}], "Mobile": [{"details": {"source": "Mobile"}, "user": "D"}]}

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