2011-08-26 24 views
8

que sigo este ejemplo: http://groups.google.com/group/clojure/browse_thread/thread/99b3d792b1d34b56clojure mapa Filtrar por teclas

(ver la última respuesta)

y este es el error críptico que me sale:

Clojure 1.2.1 
user=> (def m {:a "x" :b "y" :c "z" :d "w"}) 
#'user/m 
user=> (filter #(some % [:a :b]) m) 
java.lang.IllegalArgumentException: Key must be integer 
(user=> 

También me Don No entiendo por qué esto funcionaría. ¿No (algunos ...) devolverá el primer valor coincidente, "x", cada vez? Soy un novato total en Clojure y solo trato de aprender.

Por favor aclararme.

+0

El código del subproceso ggroup al que enlaza soluciona un problema diferente: "dado * una colección de * mapas y un conjunto de claves, devuelva una colección de precisamente aquellos de los mapas dados que contienen al menos una de las claves dadas ". Por lo tanto, en este código, 'filter' está destinado a operar en una colección de mapas, no en un solo mapa; y este particular '' (...) 'bloque que involucra' algunos' solo es apropiado si los mapas dados no contienen valores 'nil' o' false' (como se menciona en el hilo), pero en cualquier caso, la función los retornos se aplicarán (perezosamente) a cada uno de los mapas dados por turno. –

+0

bien eso explica mi malentendido, gracias. – Kevin

Respuesta

8

Si "itera" sobre un mapa, obtendrá pares clave-valor en lugar de claves. Por ejemplo,

user=> (map #(str %) {:a 1, :b 2, :c 3}) 
    ("[:a 1]" "[:b 2]" "[:c 3]") 

lo tanto su función anónima trata de evaluar (some [:a "x"] [:a :b]) que claramente no funciona.

La solución ideomática es usar select-keys como se menciona en otra respuesta.

+5

solo un poco de nitidez: se podría decir (map str {: a 1: b 2}) que es un poco más idiomático. str y # (str%) son funcionalmente equivalentes. – Gert

26

Creo que sólo necesitaba leer los documentos más:

(select-keys m [:a :b]) 

Aunque todavía no estoy seguro de lo que la intención era con el ejemplo que he encontrado ...

1
(filter 
    (fn [x] 
    (some #{(key x)} [:a :b])) m) 

Haría lo mismo usando filter y some (pero más feo y más lento).

Esto funciona por filtro todo desde m si alguno [:a :b] está en el conjunto (es decir, utilizando un conjunto como predicado) y luego devuelve la entrada del mapa.