【问题标题】:Using recursion with .reduce() to delete specific properties from a nested array of objects使用带有 .reduce() 的递归从嵌套的对象数组中删除特定属性
【发布时间】:2019-03-23 19:00:16
【问题描述】:

我正在处理从 API 获取的嵌套对象数组:

const myObj = [
    {
        "$id":"1",
        "Description":"WA State",
        "Place":"WA",
        "Data":[
        {
            "$id":"2",
            "Description":"Years",
            "Indicators":[
            {
                "$id":"3",
                "Year":2017,
                "Points":22191,
                "Goal":"28000",
                "Description":"Year 2017"
            },
            {
                "$id":"4",
                "Year":2018,
                "Points":25994,
                "Goal":"28000",
                "Description":"Year 2018"
            }
            ]
        },
        {
            "$id":"5",
            "Description":"Local Goal",
            "Indicators":[
            {
                "$id":"6",
                "Year":2018,
                "Points":25994,
                "Goal":"28000",
                "Description":"Year 2018"
            }
            ]
        },
        {
            "$id":"7",
            "Description":"Remote Goal",
            "Indicators":[
            {
                "$id":"8",
                "Year":2018,
                "Points":55857,
                "Goal":"84000",
                "Description":"Year 2018"
            }
            ]
        }
        ]
    },

    {
        "$id":"9",
        "Description":"NY State",
        "Place":"NY",
        "Data":[
        {
            "$id":"10",
            "Description":"Years",
            "Indicators":[
            {
                "$id":"11",
                "Year":2017,
                "Points":23451,
                "Goal":"27000",
                "Description":"Year 2017"
            },
            {
                "$id":"12",
                "Year":2018,
                "Points":21953,
                "Goal":"26000",
                "Description":"Year 2018"
            }
            ]
        },
        {
            "$id":"13",
            "Description":"Local Goal",
            "Indicators":[
            {
                "$id":"14",
                "Year":2018,
                "Points":24195,
                "Goal":"25000",
                "Description":"Year 2018"
            }
            ]
        },
        {
            "$id":"15",
            "Description":"Remote Goal",
            "Indicators":[
            {
                "$id":"16",
                "Year":2018,
                "Points":80857,
                "Goal":"90000",
                "Description":"Year 2018"
            }
            ]
        }
        ]
    }
];

我需要从对象中删除所有$idDescription 属性,但不改变对象。我正在尝试使用.reduce()

const props = ['$id', 'Descripcion'];

function removeKeys(obj, prop){
  return props.map( (prop, index) => Object.keys(obj).reduce((object, key) => {
    if (key !== prop[index]) {
      object[key] = obj[key]
    }
    if(object.hasOwnProperty(key))
      removeKeys(obj, prop[index])
    return object
  }, {})
  )
}

console.log( removeKeys(myObj, props) );

// RangeError: Maximum call stack size exceeded

而且不起作用。关于如何使用.reduce()

实现这一点的任何想法

PD:我的问题不是重复,因为我提到并指定使用reduce 来实现目标。在另一个问题中,答案是关于使用"for...loop" 语法。

【问题讨论】:

  • 为什么需要使用reduce来完成?
  • 因为我不想改变状态,而且我正在寻找一种优雅的方式来做到这一点。
  • 首先,不要担心优雅,而要担心一些有用的东西。听起来你想要一个单独的新数组(对象)?
  • 是的,但是...用reduce 来做这件事有点困难?
  • 有人否决我的答案的原因是什么?我已经用问题作者选择的方法提出了解决方案

标签: javascript arrays object recursion data-manipulation


【解决方案1】:

您忘记检查属性是对象还是对象数组。此外,您还使用映射函数的 prop 参数浅化了 removeKeysprop 参数。基本上这段代码可以解决问题:

const props = ['$id', 'Description'];

function removeKeys(obj){
  return Object.keys(obj).reduce((object, key) => {
     if (Array.isArray(obj[key])) {
       object[key] = obj[key].map(item => removeKeys(item));
     }
     
     else if (typeof obj[key] === 'object') {
       console.log(object);
       object[key] = removeKeys(obj[key]);
     }
     
     else if (props.indexOf(key) === -1) {
       object[key] = obj[key];
     }
     
     return object;
  }, {});
}

console.log( removeKeys(myObj) );
<script>
  myObj = 
    {
        "$id":"1",
        "Description":"WA State",
        "Place":"WA",
        "Data":[
        {
            "$id":"2",
            "Description":"Years",
            "Indicators":[
            {
                "$id":"3",
                "Year":2017,
                "Points":22191,
                "Goal":"28000",
                "Description":"Year 2017"
            },
            {
                "$id":"4",
                "Year":2018,
                "Points":25994,
                "Goal":"28000",
                "Description":"Year 2018"
            }
            ]
        },
        {
            "$id":"5",
            "Description":"Local Goal",
            "Indicators":[
            {
                "$id":"6",
                "Year":2018,
                "Points":25994,
                "Goal":"28000",
                "Description":"Year 2018"
            }
            ]
        },
        {
            "$id":"7",
            "Description":"Remote Goal",
            "Indicators":[
            {
                "$id":"8",
                "Year":2018,
                "Points":55857,
                "Goal":"84000",
                "Description":"Year 2018"
            }
            ]
        }
        ]
    };
</script>

【讨论】:

  • 有人否决我的帖子的原因是什么?我已经用问题作者选择的方法提出了解决方案
  • 感谢您的回答 Volodymyr。我赞成你的回答。而且,我已经读到可以在reduce 中使用spread operator,正如您在主题“删除属性” 中看到的here。你也知道吗?
  • 是的,您也可以使用扩展运算符(Object.assign 也可以做到这一点)。但是,您将需要遍历属性并检查它们是否是对象。为什么?因为扩展运算符不会深度克隆。因此,如果您将使用扩展运算符克隆原始对象,然后更改嵌套在其中的对象内的某些内容,那么您也会改变原始对象。
  • 如果它解决了您的问题,您也可以将此答案标记为正确的答案
  • 能否请您也使用Object.assignspread operators 发布答案?这是为了理解。
猜你喜欢
  • 2019-03-23
  • 1970-01-01
  • 2021-10-29
  • 2019-11-02
  • 1970-01-01
  • 2021-01-30
  • 2021-04-24
  • 2018-10-03
  • 2022-11-13
相关资源
最近更新 更多