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 } } }
答案 0 :(得分:30)
以下是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';
});
答案 1 :(得分:3)
在延伸georg的答案中,这就是我正在使用的内容。 这个扩展的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);
}
},
});
答案 2 :(得分:1)
编辑:这将映射对象值,而不是其键。我误解了这个问题。
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传递当前值和键。返回的值将替换新对象的现有值。它不会改变原始对象。
答案 3 :(得分:1)
我从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);
}
},
});
答案 4 :(得分:0)
就性能而言,这不是最好的选择,但是如果您想从自己的角度跳过递归部分,并希望保持代码简洁明了,则可以将其字符串化为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>