collections clojure

collections - Pon un elemento en la cola de una colección



clojure (4)

Me encuentro haciendo muchas cosas:

(concat coll [e]) donde coll es una colección y un elemento individual.

¿Hay alguna función para hacer esto en Clojure? Sé que conj hace el mejor trabajo para los vectores, pero no sé de antemano qué coll se utilizará. Podría ser un vector, una lista o un conjunto ordenado, por ejemplo.


Algunos tipos de colecciones se pueden agregar de forma barata al frente (listas, seq), mientras que otros pueden agregarse a bajo costo (vectores, colas, algo así como perezosos). En lugar de utilizar concat, si es posible, debe organizarse para trabajar con uno de esos tipos (el vector es más común) y solo conjuntarlo: (conj [1 2 3] 4) produce [1 2 3 4] , mientras que (conj ''(1 2 3) 4) rendimientos (4 1 2 3) .


Esta es una adición muy pequeña a la respuesta de @ amalloy para abordar la solicitud de OP de una función que siempre se agrega a la cola de cualquier tipo de colección. Esta es una alternativa a (concat coll [x]) . Solo crea una versión vectorial de la colección original:

(defn conj* [s x] (conj (vec s) x))

Advertencias:

Si comenzó con una secuencia floja, ahora ha destruido la pereza, es decir, la salida no es floja. Esto puede ser bueno o malo, según sus necesidades.

Hay algún costo para crear el vector. Si necesita llamar mucho a esta función, y encuentra (por ejemplo, haciendo un benchmarking con Criterium) que este costo es significativo para sus propósitos, entonces siga los consejos de las otras respuestas para tratar de usar vectores en primer lugar.


Para destilar lo mejor de lo que ya han dicho amalloy y Laurent Petit: usa la función conj .

Una de las grandes abstracciones que proporciona Clojure es la API de Secuencia, que incluye la función conj . Si es posible, su código debe ser tan independiente de la colección como puede ser, en su lugar, utilice la API de seq para manejar operaciones en colecciones y elegir un tipo de colección particular solo cuando necesite ser específico.

Si los vectores son una buena coincidencia, entonces sí, conj agregará elementos al final. Si usa listas en su lugar, entonces conj agregará cosas al frente de su colección. Pero si luego usa las funciones de API seq estándar para extraer elementos de la "parte superior" de una colección (la parte posterior de un vector, la parte delantera de una lista), no importa qué implementación use, porque siempre usará el que tenga el mejor rendimiento y, por lo tanto, agregar y eliminar elementos será consistente.


concat no agrega un elemento a la cola de una colección, ni concatena dos colecciones.

concat devuelve un seq hecho de la concatenación de otros dos seqs. El tipo original de las colecciones a partir del cual se pueden inferir los seq se pierden para el tipo de devolución de concat.

Ahora, las colecciones clojure tienen diferentes propiedades que uno debe conocer para escribir un código eficiente, es por eso que no hay una función universal disponible en el núcleo para concatenar colecciones de ningún tipo juntas. Por el contrario, la lista y los vectores tienen "posiciones de inserción naturales" que conj conoce y hace lo correcto para el tipo de colección.