假设:
{:o {:i1 1
:i2 {:ii1 4}}}
我想在"绝对"中迭代地图的键。从根形成一个向量。所以我想:
{
[:o :i1] 1
[:o :i2 :ii1] 4
}
结果。基本上只获取叶节点。
答案 0 :(得分:3)
我认为使用for
代替mapcat
的版本更为出色:
(defn flatten-keys [m]
(if (not (map? m))
{[] m}
(into {}
(for [[k v] m
[ks v'] (flatten-keys v)]
[(cons k ks) v']))))
该函数自然是递归的,非映射的最方便的基本情况是“这一个值,没有keyseq导致它”。对于地图,您只需在地图中的每个值上调用flatten-keys
,并将其键前置于结果地图的每个keyseq。
答案 1 :(得分:2)
看起来这基本上是嵌套键的扁平化。这似乎也是a 4clojure problem。
flatten-map search on github会产生很多结果。
一个示例实现:
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string pattern = @"(?x)^(\w+-\w+-\w+-\w+)$";
Regex reg = new Regex(pattern);
string test = "word-6798-3401-001";
if((reg.Match(test).Success))
foreach (var x in test.Split(new char[] {'-'}))
Console.WriteLine(x);
}
}
实施例
(defn flatten-map
"Flattens the keys of a nested into a map of depth one but
with the keys turned into vectors (the paths into the original
nested map)."
[s]
(let [combine-map (fn [k s] (for [[x y] s] {[k x] y}))]
(loop [result {}, coll s]
(if (empty? coll)
result
(let [[i j] (first coll)]
(recur (into result (combine-map i j)) (rest coll)))))))
来自Christoph Grand的更为通用的版本:
(flatten-map {:OUT
{:x 5
:x/A 21
:x/B 33
:y/A 24}})
=> {[:OUT :x] 5, [:OUT :x/A] 21, [:OUT :x/B] 33, [:OUT :y/A] 24}
示例:
(defn flatten-map
"Take a nested map (or a nested collection of key-value pairs) and returns a
sequence of key-value pairs where keys are replaced by the result of calling
(reduce f pk path) where path is the path to this key through the nested
maps."
([f kvs] (flatten-map f nil kvs))
([f pk kvs]
(mapcat (fn [[k v]]
(if (map? v)
(flatten-map f (f pk k) v)
[[(f pk k) v]])) kvs)))