1
votes

Comment trier la carte imbriquée par clés?

Ce

{0 {:data {0 1, 3 4, 7 2}}, 1 {:data {0 0, 1 1, 2 3}}}

doit être trié comme ceci

{0 {:data {7 2, 0 1, 3 4}}, 1 {:data {2 3, 1 1, 0 0}}}


0 commentaires

3 Réponses :


4
votes

Vous pouvez utiliser une carte triée, par exemple

(sort-data {0 {:data {7 2, 0 1, 3 4}}, 1 {:data {2 3, 1 1, 0 0}}})

puis

(defn- sort-map [m]
  (into (sorted-map) m))

(defn sort-data [m]
  (->> m
       (map (fn [[k v]] [k (update v :data sort-map)]))
       (into {})))


0 commentaires

2
votes

J'ai une fonction unlazy que j'utilise pour convertir des données en une forme canonique. Il parcourt récursivement n'importe quelle structure de données, convertissant tous les types séquentiels en vecteurs, et toutes les cartes / ensembles en versions triées. Il convertit également les types Java natifs en l'équivalent Clojure:

(ns demo.core
  (:require [clojure.walk :as walk]))

(defn walk-sorted
  [coll]
  (let [sort-item   (fn [item]
                      (cond    
                        (map? item) (into (sorted-map) item)
                        (set? item) (into (sorted-set) item) ]
                        :else item)) ]
      (walk/prewalk sort-item coll)))  ; or postwalk

Pour un cas simple, il pourrait être réduit comme suit:

(defn unlazy
  "Converts a lazy collection to a concrete (eager) collection of the same type."
  [coll]
  (let [unlazy-item (fn [item]
                      (cond
                        (sequential? item) (vec item)

            #?@(:clj  [ (map? item) (into (sorted-map-generic) item)
                        (set? item) (into (sorted-set-generic) item) ]
                :cljs [ (map? item) (into (sorted-map) item) ; #todo => (sorted-map-generic)
                        (set? item) (into (sorted-set) item) ; #todo => (sorted-map-generic)
                      ] )

            #?@(:clj [
                        (instance? java.io.InputStream item) (slurp item)  ; #todo need test
                        (instance? java.util.List item) (vec item)  ; #todo need test
                        (instance? java.util.Map item) (into {} item)  ; #todo need test
                        (instance? java.lang.Iterable item) (into [] item)  ; #todo need test
                     ])
                        :else item))
        result    (walk/prewalk unlazy-item coll) ]
    result))

S'il vous plaît notez que les cartes / ensembles triés ne sont utiles que pour imprimer dans un bon format (pour faciliter la lecture). Sinon, cela n'affectera pas la façon dont votre programme s'exécute.

Pour des raisons avancées, vous souhaiterez peut-être explorer la clojure.data.avl bibliothèque et la documentation de l'API .


0 commentaires

3
votes

voilà, je fais de nouveau la promotion de spectre ! (comme s'il avait besoin d'une promotion):

(require '[com.rpl.specter :refer [transform MAP-VALS]])

(transform [MAP-VALS :data] #(into (sorted-map) %) data)
;;=> {0 {:data {0 1, 3 4, 7 2}}, 1 {:data {0 0, 1 1, 2 3}}}


1 commentaires

Bonne bibliothèque à première vue, j'ai besoin de la regarder plus en détail