2017-09-04 1 views
1

J'ai une carte dans un vecteur dans une carte.Mise à jour d'une carte imbriquée dans un vecteur dans une carte

{ :label "Apparel & Accessories", 
    :img_class "itm_3", 
    :children [ 
      {:id "sub1", 
       :label "Clothing", 
       :markup [:div] 
      } 
      {:id "sub2", 
       :label "Shoes & Footwear", 
       :markup [:div] 
      } 
    ] 
} ` 

Ce que je veux faire est dissoc la clé: balisage de toutes les entrées. J'ai lutté avec cela pendant 2 heures. Ce n'est que loin que j'ai obtenu la clé: les enfants. Mais l'exigence est d'enlever: la clé de balisage seulement.

sortie finale devrait donc être

{ :label "Apparel & Accessories", 
    :img_class "itm_3", 
    :children [ 
      {:id "sub1", 
       :label "Clothing", 
      } 
      {:id "sub2", 
       :label "Shoes & Footwear", 
      } 
    ] 
} ` 

Toute contribution est très appréciée.

+1

Vous pouvez envisager Specter, qui fait ce que vous voulez dans une ligne de code: https://github.com/nathanmarz/specter#specter- – bfontaine

Répondre

0

Si votre carte initiale est m, une solution possible est ce

(assoc m :children (mapv #(dissoc % :markup) (m :children))) 

Il prend la valeur de :children, supprime les :markup clés et remplace le résultat à la carte initiale.

+0

Je reçois une erreur "ClassCastException clojure.lang.LazySeq ne peut pas être casté en clojure.lang.IFn" – shan

2

Il est une bonne habitude de faire le changement « en une seule fois »:

(update m :children (fn [v] (assert (vector? v)) (mapv #(dissoc % :markup) v))) 

Ici m est uniquement appelé une fois. Il serait important par exemple si vous faisiez un swap!.

Si vous ne disposez pas d'un vecteur, mais voulez créer un à la volée puis cela fonctionnera:

(update m :children (fn [xs] 
         (->> xs 
          vec 
          (mapv #(dissoc % :markup))))) 

Mais d'autre part il n'y a pas vraiment besoin d'être en utilisant des vecteurs. La solution originale sans assert fonctionne très bien quand :children est réglé sur:

'({:id "sub1", 
    :label "Clothing", 
    :markup [:div]} 
{:id  "sub2", 
    :label "Shoes & Footwear", 
    :markup [:div]}) 
+0

Je pense que ma carte est paresseuse. Avec votre solution, j'obtiens une erreur "ClassCastException clojure.lang.LazySeq ne peut pas être converti en clojure.lang.Associative" – shan

+0

AssertionError Assert failed: (vector? V) – shan

+0

Donc vos données sont différentes de celles de votre question. Vous pouvez utiliser 'into []' pour changer vos données. Mais je vais prendre l'assertion et la faire fonctionner localement ... –

1

Je l'ai résolu en deux étapes, pas un seul malheureusement.

(def m { :label "Apparel & Accessories", :img_class "itm_3", :children [ {:id "sub1", :label "Clothing", :markup [:div] } {:id "sub2", :label "Shoes & Footwear", :markup [:div] } ] }) 

(defn dissoc-markup [child] 
    (dissoc child :markup)) 

(update m :children #(mapv dissoc-markup %)) 
1

Si vous êtes sûr que vous souhaitez supprimer: balisage chaque fois que vous le voyez, voici un moyen simple de le faire:

(def your-data {:your-data "...."}) 
(clojure.walk/postwalk (fn [m] 
         (if (map? m) 
          (dissoc m :markup) 
          m)) 
         your-data)