javascript Deep map/transform js对象,具有更改键和值的能力

p8h8hvxi  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(101)

我见过很多在对象上进行“深度Map”的解决方案,它们要么改变对象的键,要么改变对象的值,但不能同时改变两者。
例如,如果给定以下对象:

const obj = {
  this: {
    is_not: {
      something: "we want to keep"
    },
    is: {
      a: {
        good_idea: 22
      },
      b: {
        bad_idea: 67
      },
      c: [{
        meh_idea: 22
      }]
    }
  }
}

本质上,我希望能够用以下函数签名转换它:

const newObj = deepTransform(obj, iterator)

function iterator (key, value) {
  if (key.endsWith("idea")) return { [key.replace("idea", "")]: value + 1} 
  else if (key === "is_not") return {}
  else return {[key]: value}
}

运行deepTransform将导致一个看起来像这样的对象:

{
  this: {
    is: {
      a: {
        good: 23
      },
      b: {
        bad: 68
      },
      c: [{
        meh: 23
      }]
    }
  }
}

如果有人能帮我创建这个函数,那就太棒了!如果它在引擎盖下使用lodash函数,我会非常高兴。
如果有不清楚的地方,请询问。谢谢!

js81xvg6

js81xvg61#

你可以使用lodash的_.transform()递归迭代对象/数组,并使用更新的键和值重建它们:

const { transform, toPairs, isObject } = _

const deepTransform = (obj, iterator) => transform(obj, (acc, val, key) => {
  const pair = toPairs(iterator(key, val))[0] // use the iterator and get a pair of key and value
  
  if(!pair) return // if pair is undefined, continue to next iteration
  
  const [k, v] = pair // get the update key and value from the pair
  
  // set the updated key and value, and if the value is an object iterate it as well
  acc[k] = isObject(v) ? deepTransform(v, iterator) : v 
})

const obj = {"this":{"is_not":{"something":"we want to keep"},"is":{"a":{"good_idea":22},"b":{"bad_idea":67},"c":[{"meh_idea":22}]}}}

const iterator = (key, value) => {
  if (String(key).endsWith("_idea")) return { [key.replace("_idea", "")]: value + 1} 
  
  if (key === "is_not") return {}
  
  return {[key]: value}
}

const newObj = deepTransform(obj, iterator)

console.log(newObj)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

修改迭代器a以返回一对[key,value],将使_.toPairs()冗余,并将简化代码:

const { transform, isObject, isUndefined } = _

const deepTransform = (obj, iterator) => transform(obj, (acc, val, key) => {
  const [k, v] = iterator(key, val) // use the iterator and get a pair of key and value
  
  if(isUndefined(k)) return // skip if no updated key
  
  // set the updated key and value, and if the value is an object iterate it as well
  acc[k] = isObject(v) ? deepTransform(v, iterator) : v 
})

const obj = {"this":{"is_not":{"something":"we want to keep"},"is":{"a":{"good_idea":22},"b":{"bad_idea":67},"c":[{"meh_idea":22}]}}}

const iterator = (key, value) => {
  if (String(key).endsWith("_idea")) return [key.replace("_idea", ""), value + 1]
  
  if (key === "is_not") return []
  
  return [key, value]
}

const newObj = deepTransform(obj, iterator)

console.log(newObj)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

相关问题