在 Clojure 中将函数映射到映射的值
我想将一个值映射转换为具有相同键但对值应用了函数的另一个映射。我认为 clojure api 中有一个函数可以做到这一点,但我一直找不到它。
这是我正在寻找的示例实现
(defn map-function-on-map-vals [m f]
(reduce (fn [altered-map [k v]] (assoc altered-map k (f v))) {} m))
(println (map-function-on-map-vals {:a "test" :b "testing"} #(.toUpperCase %)))
{:b TESTING, :a TEST}
有人知道 map-function-on-map-vals
是否已经存在?我认为确实如此(可能还有一个更好听的名字)。
I want to transform one map of values to another map with the same keys but with a function applied to the values. I would think there was a function for doing this in the clojure api, but I have been unable to find it.
Here's an example implementation of what I'm looking for
(defn map-function-on-map-vals [m f]
(reduce (fn [altered-map [k v]] (assoc altered-map k (f v))) {} m))
(println (map-function-on-map-vals {:a "test" :b "testing"} #(.toUpperCase %)))
{:b TESTING, :a TEST}
Does anybody know if map-function-on-map-vals
already exists? I would think it did (probably with a nicer name too).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
我很喜欢你的
reduce
版本。我认为这是惯用的。无论如何,这是一个使用列表理解的版本。I like your
reduce
version just fine. I think it's idiomatic. Here's a version using list comprehension anyways.您可以使用
clojure.algo.generic.functor/fmap
:You can use the
clojure.algo.generic.functor/fmap
:这是一种相当典型的转换地图的方法。
zipmap
接受一个键列表和一个值列表,并“做正确的事情”,生成一个新的 Clojure 映射。您还可以将map
放在按键周围来更改它们,或两者都更改。或者将其包装在您的函数中:
Here is a fairly typical way to transform a map.
zipmap
takes a list of keys and a list of values and "does the right thing" producing a new Clojure map. You could also put themap
around the keys to change them, or both.or to wrap it up in your function:
摘自《Clojure Cookbook》,有reduce-kv:
Taken from the Clojure Cookbook, there is reduce-kv:
Clojure 1.11 在标准库
clojure.core
中添加了一个函数。 Clojure 1.11 于 2022 年 3 月 22 日发布。update-vals
< /a>(update-vals mf)
将函数应用于映射中的每个值。它返回一个新的映射{k (fv) ...}
。用法
另请参阅:
update-keys
(update-keys mf)
将函数应用于映射中的每个键。它返回一个新地图{(fk) v ...}
。(fk)
产生的所有键必须是唯一的。Clojure 1.11 中也添加了此功能。
用法
Clojure 1.11 added a function for this to
clojure.core
, the standard library. Clojure 1.11 was released on 2022-03-22.update-vals
(update-vals m f)
applies the function to every value in the map. It returns a new map{k (f v) ...}
.Usage
See also:
update-keys
(update-keys m f)
applies the function to every key in the map. It returns a new map{(f k) v ...}
. All keys resulting from(f k)
must be unique.This function, too, was added in Clojure 1.11.
Usage
这是一种相当惯用的方法:
示例:
Here's a fairly idiomatic way to do this:
Example:
map-map
、map-map-keys
和map-map-values
我知道 Clojure 中没有现有的函数,但这里有该函数的实现为您可以自由复制的
map-map-values
。它带有两个密切相关的函数,map-map
和map-map-keys
,标准库中也缺少这些函数:用法
您可以调用
map- map-values
像这样:另外两个函数像这样:
替代实现
如果您只想要
map-map-keys
或map-map-values
,如果没有更通用的map-map
函数,您可以使用这些实现,它们不依赖于map-map
:此外,这里还有一个
map 的替代实现-map
基于clojure.walk/walk
< /a> 而不是into
(如果您更喜欢这种措辞) :并行版本 -
pmap-map
等。如果您需要,这些函数也有并行版本。他们只是使用
pmap
而不是地图
。map-map
,map-map-keys
, andmap-map-values
I know of no existing function in Clojure for this, but here’s an implementation of that function as
map-map-values
that you are free to copy. It comes with two closely related functions,map-map
andmap-map-keys
, which are also missing from the standard library:Usage
You can call
map-map-values
like this:And the other two functions like this:
Alternative implementations
If you only want
map-map-keys
ormap-map-values
, without the more generalmap-map
function, you can use these implementations, which don’t rely onmap-map
:Also, here’s an alternative implementation of
map-map
that is based onclojure.walk/walk
instead ofinto
, if you prefer this phrasing:Parellel versions –
pmap-map
, etc.There are also parallel versions of these functions if you need them. They simply use
pmap
instead ofmap
.我是 Clojure n00b,所以很可能有更优雅的解决方案。这是我的:
anon func 根据每个键及其 f'ed 值创建一个小 2-列表。 Mapcat 在地图键的序列上运行此函数,并将整个作品连接成一个大列表。 “apply hash-map”根据该序列创建一个新的映射。 (% m) 可能看起来有点奇怪,它是 Clojure 的惯用用法,用于将键应用于映射以查找关联的值。
最强烈推荐阅读:Clojure Cheat Sheet 。
I'm a Clojure n00b, so there may well be much more elegant solutions. Here's mine:
The anon func makes a little 2-list from each key and its f'ed value. Mapcat runs this function over the sequence of the map's keys and concatenates the whole works into one big list. "apply hash-map" creates a new map from that sequence. The (% m) may look a little weird, it's idiomatic Clojure for applying a key to a map to look up the associated value.
Most highly recommended reading: The Clojure Cheat Sheet .
我喜欢你的
reduce
版本。通过非常微小的变化,它还可以保留记录结构的类型:{}
被m
替换。进行此更改后,记录仍然是记录:通过以
{}
开头,记录将失去其记录性,如果您需要记录功能(紧凑内存),则可能希望保留该记录性例如代表)。I like your
reduce
version. With a very slight variation, it can also retain the type of records structures:The
{}
was replaced bym
. With that change, records remain records:By starting with
{}
, the record loses its recordiness, which one might want to retain, if you desire the record capabilities (compact memory representation for instance).我想知道为什么还没有人提到 specter 库。它的编写是为了使这种转换易于编码(更重要的是,编写的代码易于理解),同时仍然非常高效:
用纯 Clojure 编写这样的函数很简单,但代码变得更加棘手一旦您转向由不同数据结构组成的高度嵌套的代码。这就是幽灵的用武之地。
我建议观看这一集 解释了 spectre 背后的动机和细节。
I'm wondering why nobody has mentioned the specter library yet. It has been written to make this kind of transform easy to code (and, even more important, the written code easy to understand), while still being very performant:
Writing such a function in pure Clojure is simple, but the code gets much trickier once you move on to highly nested code composed of different data structures. And this is where specter comes in.
I recommend watching this episode on Clojure TV which explains the motivation behind and details of specter.
Clojure 1.7(发布 2015 年 6 月 30 日)提供了一个优雅的解决方案与
update
一起使用:Clojure 1.7 (released June 30, 2015) provides an elegant solution for this with
update
: