J'ai un ensemble de données comme celui-ci
{
"target_groups": [
{
"target_group_id": "1234",
"target_group_name": "abc",
"targets": [
{
"target_id": "456",
"target_name": "john"
},
{
"target_id": "789",
"target_name": "doe"
}
]
},
{
"target_group_id": "56789",
"target_group_name": "cdes",
"targets": [
{
"target_id": "0987",
"target_name": "john"
}
]
}
]
}
et je souhaite effectuer une transformation en regroupant et en fusionnant les données par ID de groupe cible afin que la cible du même target_group_id soit ajoutée au groupe cible existant et changer la racine clé des données de "data" en "target_groups"
{
"data": [
{
"target_group_id": "1234",
"target_group_name": "abc",
"targets": [
{
"target_id": "456",
"target_name": "john"
}
]
},
{
"target_group_id": "56789",
"target_group_name": "cdes",
"targets": [
{
"target_id": "0987",
"target_name": "john"
}
]
},
{
"target_group_id": "1234",
"target_group_name": "abc",
"targets": [
{
"target_id": "789",
"target_name": "doe"
}
]
}
]
}
y a-t-il un moyen efficace de le faire avec clojure depuis mon code original en utilisant php et en prendre beaucoup de "if-clause" et "foreach"? merci ...
3 Réponses :
Voici comment je l'aborderais:
(is= data-edn
{:data
[{:target_group_id "1234",
:target_group_name "abc",
:targets [{:target_id "456", :target_name "john"}]}
{:target_group_id "56789",
:target_group_name "cdes",
:targets [{:target_id "0987", :target_name "john"}]}
{:target_group_id "1234",
:target_group_name "abc",
:targets [{:target_id "789", :target_name "doe"}]}]})
(is= d2
{"1234"
[{:target_group_id "1234",
:target_group_name "abc",
:targets [{:target_id "456", :target_name "john"}]}
{:target_group_id "1234",
:target_group_name "abc",
:targets [{:target_id "789", :target_name "doe"}]}],
"56789"
[{:target_group_id "56789",
:target_group_name "cdes",
:targets [{:target_id "0987", :target_name "john"}]}]})
(is= d3
[{:tgt-group-id "1234",
:tgt-group-name "abc",
:targets-all [[{:target_id "456", :target_name "john"}]
[{:target_id "789", :target_name "doe"}]]}
{:tgt-group-id "56789",
:tgt-group-name "cdes",
:targets-all [[{:target_id "0987", :target_name "john"}]]}]) ))
avec transformation:
(dotest
(let [data-edn (t/json->edn
(ts/quotes->double data-json))
d2 (t/it-> data-edn
(:data it) ; unnest from :data key
(group-by :target_group_id it ) )
d3 (t/forv [[tgt-id entries] d2]
{:tgt-group-id tgt-id
:tgt-group-name (:target_group_name (first entries))
:targets-all (mapv :targets entries)}) ]
et résultats / tests:
XXX
En utilisant uniquement le core clojure (avec la bibliothèque data.json).
Premièrement, acquérez et développez nos données:
(def output (->> data
(group-by #(get % "target_group_id"))
vals
(map #(reduce concat-targets %))
(assoc {} "target_groups")
clojure.data.json/write-str))
Lorsque nous adressons des groupes de cibles, nous vont avoir besoin de les concaténer. Je faisais cela en ligne, mais cela semble compliqué dans la réduction, alors voici une fonction d'aide:
(defn concat-targets [acc item] (update acc "targets" concat (item "targets")))
Alors faisons le travail!
(def data (-> "grouping-and-merging.json"
slurp
clojure.data.json/read-str
(get "data")))
Une autre façon de faire la transformation:
(def merge-vector
(partial apply
merge-with
(fn [& xs] (if (every? vector? xs) (apply concat xs) (last xs)))))
La structure de données intermédiaire est une séquence de set indexée par identifiant de groupe et nom de groupe (comme en utilisant group-by ). Ie
(-> "data.json"
slurp
json/read-str
(get "data")
(set/index ["target_group_id" "target_group_name"])
vals)
;; =>
(#{{"target_group_id" "1234",
"target_group_name" "abc",
"targets" [{"target_id" "789", "target_name" "doe"}]}
{"target_group_id" "1234",
"target_group_name" "abc",
"targets" [{"target_id" "456", "target_name" "john"}]}}
#{{"target_group_id" "56789",
"target_group_name" "cdes",
"targets" [{"target_id" "0987", "target_name" "john"}]}})
Les cibles (qui est un vecteur ) sont alors concat avec merge-vector:
{"target_groups" (map merge-vector (-> "data.json"
slurp
json/read-str
(get "data")
(set/index ["target_group_id" "target_group_name"])
vals))}
;; =>
{"target_groups"
({"target_group_id" "1234",
"target_group_name" "abc",
"targets"
({"target_id" "789", "target_name" "doe"}
{"target_id" "456", "target_name" "john"})}
{"target_group_id" "56789",
"target_group_name" "cdes",
"targets" [{"target_id" "0987", "target_name" "john"}]})}
J'ai répondu, mais j'ai réalisé que ma réponse avait un défaut, alors éditer maintenant