[英]How to deeply map object keys with JavaScript (lodash)?
https://lodash.com/docs#mapKeys
是否可以使用 Lodash 深入 map 对象的键? 如果没有,是否有另一个库提供此功能(如果与其他深度迭代和操作功能组合在一起,甚至更好?),否则? go 如何实现这一点,我看到的主要困难是识别安全的纯键/值对象。 deeply iterable,抛出 Arrays 很容易,但需要注意的是 function 不应该像正则表达式那样尝试对其他对象进行深度迭代。 例如。
预期结果-
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 } } }
以下是你在lodash
如何做到这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';
});
在扩展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);
}
},
});
编辑:这将映射对象值,而不是其键。 我误解了这个问题。
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/
我从Chris Jones的答案中添加了一点改进。
下面的代码修复了一些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);
}
},
});
根据性能效率不是最好的,但是如果你想从你身边跳过递归部分并希望保持代码清洁和简单,那么你可以将它JSON.parse
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>
接受的解决方案不适用于更深层次的数组/对象/简单类型或 arrays 之类的简单类型(字符串/数字)
{
"notification-type": 1,
"reciept_my": {
"latest__info": [
{
"a-a": 1,
"reciept_my": { "latest__info": [{ "a-a": 1 }, "b", true, "d"] }
},
"b",
true,
"d"
]
}
}
例如['s']
转换为Object {0: "s"}
这是使其工作的改进:
function deepMapKeys(obj, fn) {
if (!_.isArray(obj) && !_.isPlainObject(obj)) {
return obj;
}
const x = _.isArray(obj) ? [] : {};
_.forOwn(obj, function (v, k) {
if (_.isArray(v)) {
v = v.map((v) => deepMapKeys(v, fn));
}
if (_.isPlainObject(v)) {
v = deepMapKeys(v, fn);
}
x[fn(k)] = v;
});
return x;
}
小心,如果你不直接导入它,它会抛出“deeply is not a function”错误——你需要在你的代码调用_.deeply
之前导入(或编写)这个 mixin。
import _, { Dictionary, ObjectIterator } from "lodash"
declare module "lodash" {
interface LoDashStatic {
deeply<T extends object, TResult>(map: unknown): (obj: T | null | undefined, callback: ObjectIterator<T, TResult>) => { [P in keyof T]: TResult }
}
}
_.mixin({
deeply: (map) => {
return (object: Dictionary<unknown>, callback: ObjectIterator<object, unknown>) => {
return map(_.mapValues(object, value => {
return _.isPlainObject(value) ? _.deeply(map)(value as object, callback) : value
}), callback)
}
},
})
export default {}
/**
* https://stackoverflow.com/questions/38304401/javascript-check-if-dictionary/71975382#71975382
*/
export function isDictionary(object: unknown): object is Record<keyof never, unknown> {
return object instanceof Object && object.constructor === Object
}
/**
* https://stackoverflow.com/a/75010148/12468111
*/
export function mapKeysDeep(object: Record<keyof never, unknown>, callback: (key: string, value: unknown) => keyof never): Record<string, unknown> {
function iterate(value: unknown): unknown {
if (isDictionary(value)) {
return mapKeysDeep(value, callback)
}
if (value instanceof Array) {
return value.map(iterate)
}
return value
}
return (
Object
.entries(object)
.reduce((result, [key, value]) => ({ ...result, [callback(key, value)]: iterate(value) }), {})
)
}
不要忘记放置指向您复制粘贴的代码的链接(请)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.