deepdash
Version:
➔ 𝐃eep standalone lib / 𝐋odash extension: ✓ eachDeep ✓ filterDeep ✓ mapDeep ✓ reduceDeep ✓ pickDeep ✓ omitDeep ✓ keysDeep ✓ index ✓ condenseDeep ⋮ Parents stack ⋮ Circular check ⋮ Leaves only mode ⋮ Children mode ⋮ cherry-pick ⋮ esm
81 lines (77 loc) • 2.42 kB
JavaScript
import getEachDeep from './getEachDeep.js';
import getPathToString from './getPathToString.js';
export default function getMapKeysDeep(_) {
const eachDeep = getEachDeep(_);
const pathToString = getPathToString(_);
function mapKeysDeep(obj, iteratee, options = {}) {
iteratee = _.iteratee(iteratee);
options.cloneDeep = options.cloneDeep || _.cloneDeep;
options.callbackAfterIterate = false;
const newPaths = [];
eachDeep(
obj,
function (value, key, parent, context) {
if (key === undefined) {
return;
}
const newKey = iteratee(value, key, parent, context) + '';
if (newKey === key) {
return;
}
const oldPath = context.path;
const oldPathStr =
options.pathFormat === 'array' ? JSON.stringify(oldPath) : oldPath;
const newPath =
options.pathFormat === 'array'
? [
...(context.parent.path || []),
...(context.childrenPath || []),
newKey,
]
: pathToString([newKey], context.parent.path, context.childrenPath);
const newPathStr =
options.pathFormat === 'array' ? JSON.stringify(newPath) : newPath;
if (!newPaths[context.depth - 1]) {
newPaths[context.depth - 1] = [];
}
newPaths[context.depth - 1].push({
oldPath,
oldPathStr,
newPath,
newPathStr,
});
},
options
);
const res = options.cloneDeep(obj);
let d = newPaths.length;
while (d--) {
if (!newPaths[d]) {
continue;
}
const overwritten = {};
newPaths[d].forEach(({ oldPath, oldPathStr, newPath, newPathStr }) => {
let value;
if (Object.prototype.hasOwnProperty.call(overwritten, oldPathStr)) {
value = overwritten[oldPathStr];
delete overwritten[oldPathStr];
} else {
value = _.get(res, oldPath);
if (value === undefined && !_.has(res, oldPath)) {
return;
}
_.unset(res, oldPath);
}
if (
_.has(res, newPath) &&
!Object.prototype.hasOwnProperty.call(overwritten, newPathStr)
) {
overwritten[newPathStr] = _.get(res, newPath);
}
_.set(res, newPath, value);
});
}
return res;
}
return mapKeysDeep;
}