如何使用 JavaScript (lodash) 深度映射对象键?
Posted
技术标签:
【中文标题】如何使用 JavaScript (lodash) 深度映射对象键?【英文标题】:How to deeply map object keys with JavaScript (lodash)? 【发布时间】:2016-05-05 11:43:56 【问题描述】:https://lodash.com/docs#mapKeys
是否可以使用 Lodash 深度映射对象的键?如果没有,是否有另一个库提供此功能(如果与其他深度迭代和操作功能组合在一起,那就更好了!)?否则,将如何实现这一点?我看到的主要困难是识别安全、深度可迭代的纯键/值对象。丢弃数组很容易,但重要的是要注意该函数不应尝试深度迭代其他对象,例如正则表达式。
预期结果-
var obj = a: 2, b: c: 2, d: a: 3 ;
_.deepMapKeys(obj, function (val, key)
return key + '_hi';
);
// => a_hi: 2, b_hi: c_hi: 2, d_hi: a_hi: 3
【问题讨论】:
【参考方案1】:在lodash
中您可以这样做:
_.mixin(
'deepMapKeys': function (obj, fn)
var x = ;
_.forOwn(obj, function(v, k)
if(_.isPlainObject(v))
v = _.deepMapKeys(v, fn);
x[fn(v, k)] = v;
);
return x;
);
这是一个更抽象的 mixin,它递归地应用任何给定的映射器:
_.mixin(
deep: function (obj, mapper)
return mapper(_.mapValues(obj, function (v)
return _.isPlainObject(v) ? _.deep(v, mapper) : v;
));
,
);
用法(返回同上):
obj = _.deep(obj, function(x)
return _.mapKeys(x, function (val, key)
return key + '_hi';
);
);
另一种选择,语法更优雅:
_.mixin(
deeply: function (map)
return function(obj, fn)
return map(_.mapValues(obj, function (v)
return _.isPlainObject(v) ? _.deeply(map)(v, fn) : v;
), fn);
,
);
obj = _.deeply(_.mapKeys)(obj, function (val, key)
return key + '_hi';
);
【讨论】:
这是一个很好的解决方案,所以我会支持它。但是,我发现在解决选项时接受的答案更简单,所以这是我推荐的方法。 @TejasManohar:嗯,你要求的代码是基于 lodash 的,并且能够区分普通对象和类型对象......接受的答案都不是。 不错!我需要一个版本的deeply()
也可以深入到数组中。这是:gist.github.com/zambon/8b2d207bd21cf4fcd47b96cd6d7f99c2【参考方案2】:
编辑:这将映射对象的值,而不是它的键。我误解了这个问题。
function deepMap (obj, cb)
var out = ;
Object.keys(obj).forEach(function (k)
var val;
if (obj[k] !== null && typeof obj[k] === 'object')
val = deepMap(obj[k], cb);
else
val = cb(obj[k], k);
out[k] = val;
);
return out;
并将其用作
var lol = deepMap(test, function (v, k)
return v + '_hi';
);
它将递归地遍历对象自身的可枚举属性,并调用一个 CB,将当前值和键传递给它。返回的值将替换新对象的现有值。它不会改变原始对象。
见小提琴:https://jsfiddle.net/1veppve1/
【讨论】:
重要的是要注意,这会返回一个具有不同值的新对象,而不是问题中所问的键。也就是说,这是一个简单的更改,它表达了概念上的理解,所以我会保留一个反对票:) @TejasManohar 该死的,对不起,我误解了重点。我以为您映射的是值而不是键。我会添加一个编辑,以免其他人感到困惑。 @alexanderElgin 我知道这需要付出努力,但你介意更新我的小提琴以展示一种减少冗余代码的方法吗?我并不是说听起来讽刺,我有兴趣提高我的知识和所有这些。【参考方案3】:在乔治的回答范围内,这就是我正在使用的。 这个扩展的 mixin 也增加了在对象中映射对象数组的能力,这是一个简单但重要的变化。
_.mixin(
deeply: function (map)
return function (obj, fn)
return map(_.mapValues(obj, function (v)
return _.isPlainObject(v) ? _.deeply(map)(v, fn) : _.isArray(v) ? v.map(function(x)
return _.deeply(map)(x, fn);
) : v;
), fn);
,
);
【讨论】:
【参考方案4】:我在Chris Jones's answer 基础上做了一个小改进。
以下代码修复了 Array 元素的一些意外结果。
_.mixin(
deeply: function (map)
var deeplyArray = function (obj, fn)
return obj.map(function(x)
return _.isPlainObject(x) ? _.deeply(map)(x, fn) : x;
)
return function (obj, fn)
if (_.isArray(obj))
return deeplyArray(obj, fn);
return map(_.mapValues(obj, function (v)
return _.isPlainObject(v) ? _.deeply(map)(v, fn) : _.isArray(v) ?
deeplyArray(v, fn) : v;
), fn);
,
);
【讨论】:
【参考方案5】:就性能效率而言不是最好的,但是如果您想从您身边跳过递归部分并希望保持代码简洁明了,那么您可以将其字符串化为 json 并使用 JSON.parse
和附加参数(回调)在那里你可以用 lodash 转换键。
JSON.parse(JSON.stringify(obj), (k, v) => _.isObject(v) ? _.mapKeys(v, (_v, _k) => _k + '_hi') : v)
这是一个工作示例:
let obj = a: 2, b: c: 2, d: a: 3 ;
let mappedObj = JSON.parse(JSON.stringify(obj), (k, v) => _.isObject(v) ? _.mapKeys(v, (_v, _k) => _k + '_hi') : v)
console.log(mappedObj)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
【讨论】:
以上是关于如何使用 JavaScript (lodash) 深度映射对象键?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Javascript/Lodash/ES6 中同时搜索父对象和子对象?