更新映射序列中的键的值,使用第一个映射的键的值。

huangapple go评论73阅读模式
英文:

Update values of keys in a sequence of maps from the values of first map's keys

问题

我有一系列类似这样的地图:

({:autoNo "1" :title "Title1" :47652 ("name1") :47653 ("name2" "name3")} {:autoNo nil :title nil :47652 nil :47653 nil})

只有第一个地图包含文件上传字段键:47652:47653的值,而第二个地图中相同键的值为nil。我希望文件上传字段键每个地图只有一个文件值,就像这样:

({:autoNo "1" :title "Title1" :47652 "name1" :47653 "name2"} {:autoNo nil :title nil :47652 nil :47653 "name3"})

您可以看到,正如:47652seq中只有一个值,所以它的值得到了更新,而同一键在序列中的下一个地图中的值保持为nil。对于:47653具有多个值,第一个地图中的键包含第一个值,即"name2",而序列中下一个地图中的相同键包含下一个值,即"name3"

为了实现这一点,我创建了一个函数,如下所示:

(defn update-file-upload-field-values
  [conversation-instances]
  (let [file-field-ids [:47652 :47653]]
    (first (map (fn [x]
                  (map
                   #(update %1 x (fn [z] (str %2)))
                   conversation-instances ((first conversation-instances) x)))
                file-field-ids))))

其中conversation-instances与开始时提到的地图序列相同。

我的解决方案未能达到预期的效果。它返回了这个:

({:autoNo "1" :title "Title1" :47652 "name1" :47653 ("name2" "name3")})

这与开头显示的预期输出不同。

英文:

I have a sequence of maps like this:

({:autoNo "1" :title "Title1" :47652 ("name1") :47653 ("name2" "name3")} {:autoNo nil :title nil :47652 nil :47653 nil})

Only the first map contains the values for file-upload-field keys :47652 and :47653 whereas the value of same keys in the second map is nil. What I want is file-upload-field keys having only one name of file value per map like this:

({:autoNo "1" :title "Title1" :47652 "name1" :47653 "name2"} {:autoNo nil :title nil :47652 nil :47653 "name3"})

You can see above as :47652 have only one value in the seq so its value get updated whereas the value of the same key in the next map remains nil. For :47653 having multiple values, the key in first map contains the first value i.e. "name2" whereas the same key in the second map of the sequence contains the next value i.e. "name3".

To achieve so I have created a function like this:

(defn update-file-upload-field-values
  [conversation-instances]
  (let [file-field-ids [:47652 :47653]]
    (first (map (fn [x]
                  (map
                   #(update %1 x (fn [z] (str %2)))
                   conversation-instances ((first conversation-instances) x)))
                file-field-ids))))

where conversation-instances is the same sequence of maps stated at the beginning.

My solution is not working as expected. It is returning this:

({:autoNo "1" :title "Title1" :47652 "name1" :47653 ("name2" "name3")})

Which is different from the expected output shown at the beginning.

答案1

得分: 0

你使用 map 函数同时处理两个序列(conversation-instances((first conversation-instances) x) 的结果),因此结果的长度将取决于它们中最短的那个。我还认为你可以用 assoc 替换 update

使用两层嵌套的 map 结合 first 也会产生一些你可能不想要的结果。我建议你逐步编写函数,逐步在 REPL 中测试,这样你就知道你的函数是否达到了预期的效果。

你可以使用 reduce 来解决这个问题。我的 update-maps 函数类似于你的内部 map,只是我添加了 reduce 来重复执行它以处理每个给定的键:

(def data '({:autoNo "1" :title "Title1" :47652 ("name1") :47653 ("name2" "name3")}
            {:autoNo nil :title nil :47652 nil :47653 nil}))

(defn update-maps [coll k]
  (let [values-seq (k (first coll))]
    (mapv #(assoc %1 k %2)
          coll
          (concat values-seq (repeat nil)))))

(defn keys-fn [coll]
  (let [ks [:47652 :47653]]
    (reduce update-maps
            coll
            ks)))

(keys-fn data)
=>
[{:autoNo "1", :title "Title1", :47652 "name1", :47653 "name2"} {:autoNo nil, :title nil, :47652 nil, :47653 "name3"}]
英文:

You call map with two sequences (conversation-instances and the result of ((first conversation-instances) x)), so the result will be as long as the shortest of them. I also think you can replace update with assoc.

Two nested maps with first also create some result you probably don't want. I suggest you to write your functions step by step, testing each increment in REPL, so you know whether your function does what you expect.

You can use reduce to solve this. My update-maps is similar to your inner map, I just added reduce to repeat it for each given key:

(def data '({:autoNo "1" :title "Title1" :47652 ("name1") :47653 ("name2" "name3")}
            {:autoNo nil :title nil :47652 nil :47653 nil}))

(defn update-maps [coll k]
  (let [values-seq (k (first coll))]
    (mapv #(assoc %1 k %2)
          coll
          (concat values-seq (repeat nil)))))

(defn keys-fn [coll]
  (let [ks [:47652 :47653]]
    (reduce update-maps
            coll
            ks)))

(keys-fn data)
=>
[{:autoNo "1", :title "Title1", :47652 "name1", :47653 "name2"} {:autoNo nil, :title nil, :47652 nil, :47653 "name3"}]

答案2

得分: 0

(require 'com.rpl.specter :as s)
(use 'plumbing.core)

(let [data         '({:autoNo "1" :title "Title1" :47652 ("name1") :47653 ("name2" "name3")}
                     {:autoNo nil :title nil :47652 nil :47653 nil})]
    (->> data
        (s/transform (s/subselect 
展开收缩
)]) aconcat)
(s/transform (s/subselect
展开收缩
)]) aconcat)))
英文:
(require '[com.rpl.specter :as s])
(use '[plumbing.core])

(let [data         '({:autoNo "1" :title "Title1" :47652 ("name1") :47653 ("name2" "name3")}
					 {:autoNo nil :title nil :47652 nil :47653 nil})]
	(->> data
		(s/transform (s/subselect 
展开收缩
)]) aconcat) (s/transform (s/subselect
展开收缩
)]) aconcat)))

答案3

得分: 0

基本上你可以这样做

```clojure
(map assoc 数据
     (repeat :47652)
     (concat (:47652 (first 数据)) (repeat nil))
     (repeat :47653)
     (concat (:47653 (first 数据)) (repeat nil)))

为了消除重复,你可以这样做:

(defn ks-vs [[k vs]] 
  [(repeat k) (concat vs (repeat nil))])

(defn 处理 [[头 :as 数据]]
  (->> (select-keys 头 [:47652 :47653])
       (mapcat ks-vs)
       (apply map assoc 数据)))

(处理 数据)

这基本上是基于相同方法的更抽象的变体。

英文:

basically, what you could do is something like this:

(map assoc data
     (repeat :47652)
     (concat (:47652 (first data)) (repeat nil))
     (repeat :47653)
     (concat (:47653 (first data)) (repeat nil)))

;;=> ({:autoNo "1", :title "Title1", :47652 "name1", :47653 "name2"}
;;    {:autoNo nil, :title nil, :47652 nil, :47653 "name3"})

to get rid of repetition you can do something like that:

(defn ks-vs [[k vs]] 
  [(repeat k) (concat vs (repeat nil))])

(defn process [[head :as data]]
  (->> (select-keys head [:47652 :47653])
       (mapcat ks-vs)
       (apply map assoc data)))

(process data)

;;=> ({:autoNo "1", :title "Title1", :47652 "name1", :47653 "name2"}
;;    {:autoNo nil, :title nil, :47652 nil, :47653 "name3"})

which is basically more abstract variant based on the same approach.

答案4

得分: 0

抱歉,我只能为您提供代码部分的翻译:

我讨厌回答与所问不同的问题但在您的问题中列表中的第二个映射似乎是从第一个派生出来的因此不需要

此外许多但并非所有当前的答案似乎包含硬编码的信息即键或最大项的长度

我认为有3种解决方案

  1. 循环递归
  2. 惰性映射
  3. 有状态的传递器

说到这里我将提供一个惰性的解决方案其中键和长度都没有硬编码

    (->> '{:autoNo "1" :title "Title1" :47652 ("name1") :47653 ("name2" "name3" "name4") :9999 ("foo9" "bar9")}
         (mapcat (fn [[k v]]
                   [(repeat k)
                    (if (coll? v)
                      (concat v (repeat nil))
                      (cons v (repeat nil)))]))
         (apply map hash-map)
         (take-while #(some second %)))
         
这应该产生类似以下的结果

    [{:47652 "name1" :47653 "name2" :9999 "foo" :autoNo "1" :title "Title1"}
     {:47652 nil     :47653 "name3" :9999 "bar" :autoNo nil :title nil}
     {:47652 nil     :47653 "name4" :9999  nil  :autoNo nil :title nil}]
英文:

I hate to answer a question other than what was asked but in your question, the second map in the list appears to be derived from the first and is thus not needed.

Also many (but not all) of the current answers appear to hardcoded information i.e. keys or length of maximum items.

I think there are 3 solutions:

  1. loop recur
  2. lazy mapping
  3. stateful transducer.

That being said I'll offer up a "lazy" solution that has neither the keys or lengths hard coded in:

(->> '{:autoNo "1" :title "Title1" :47652 ("name1") :47653 ("name2" "name3" "name4") :9999 ("foo9" "bar9")}
     (mapcat (fn [[k v]]
               [(repeat k)
                (if (coll? v)
                  (concat v (repeat nil))
                  (cons v (repeat nil)))]))
     (apply map hash-map)
     (take-while #(some second %)))

which should yield something like:

[{:47652 "name1" :47653 "name2" :9999 "foo" :autoNo "1" :title "Title1"}
 {:47652 nil     :47653 "name3" :9999 "bar" :autoNo nil :title nil}
 {:47652 nil     :47653 "name4" :9999  nil  :autoNo nil :title nil}]

huangapple
  • 本文由 发表于 2023年2月18日 16:12:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75492035.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定