0

I'm working with this array of nested objects, getted from an 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"
            }
            ]
        }
        ]
    }
];

I need to delete all the $id and Description properties from the objects, but not mutating the object. I'm trying to do it using .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

And does not works. Any ideas on how I can achieve this using .reduce()

PD: My question is not a duplicate of, because I'm mentioning and specifying the use of reduce to achieve the goal. In the other question, the answers are about using the "for...loop" syntax.

9
  • Why does it need to be done using reduce? Commented Oct 18, 2018 at 21:41
  • Because I don't want to mutate the state, and also I'm looking for an elegant way to do it. Commented Oct 18, 2018 at 22:03
  • First, don't worry about elegant, instead worry about something that works. Sounds like you want a separate, new array (of objects)? Commented Oct 18, 2018 at 22:09
  • Yes, but ... it is something difficult to do it with reduce ? Commented Oct 18, 2018 at 22:11
  • 1
    What is the reason someone downvoted my answer? I have proposed the solution with the approach the author of the question had chosen Commented Oct 18, 2018 at 22:24

1 Answer 1

1

You forgot to check if property is an object or an array of objects. Also you'he been shallowing prop argument of removeKeys with prop argument of your mapping function. Basically this code will do the trick:

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>

Sign up to request clarification or add additional context in comments.

5 Comments

What is the reason someone downvoted my post? I have proposed the solution with the approach the author of the question had chosen
Thanks for your answer Volodymyr. I have upvoted your answer. But also, I have read that it is possible using spread operator inside reduce, as you can see here on the topic "Deleting properties". Do you know also about that ?
Yes, you can go with spread operator (Object.assign also can do the trick) as well. However you will need to iterate over properties and check if they are objects or not. Why? Because spread operator does not clones deeply. So if you will clone your original object with spread operator and then change something inside an object nested inside you will also mutate the original object.
You can also mark this answer as the right one if it solves your issue
Can you please, post an answer too using Object.assign or spread operators? It's for the sake of understand.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.