Skip to content

Instantly share code, notes, and snippets.

@jrrio
Created April 23, 2018 15:06
Show Gist options
  • Select an option

  • Save jrrio/55f93cdfc70209f1a7ba0a8d3bb762a2 to your computer and use it in GitHub Desktop.

Select an option

Save jrrio/55f93cdfc70209f1a7ba0a8d3bb762a2 to your computer and use it in GitHub Desktop.

Revisions

  1. jrrio created this gist Apr 23, 2018.
    102 changes: 102 additions & 0 deletions reduce_Object.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    # Calculate the average of Object properties

    Here is our Object literal with some properties. What we need to do is calculate the average height of a set of people using JavaScript.

    ```javascript
    const data = {
    "Matt": { "height" : 176, "weight": 87 },
    "Jason": { "height" : 190, "weight": 103 },
    "Peter": { "height" : 180, "weight": 98 }
    };
    ```

    ## Using a for...in loop statement

    The value of the **data** constant is a reference to an Object instance, which inherits properties from *Object.prototype*. As the [for...in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) statement iterates over the enumerable properties of an Object, including those inherited from its prototype chain, we'll need to use the [hasOwnProperty()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) method so that inherited properties are not considered.

    ```javascript
    var count = 0, sumHeight = 0;
    for (var key in data) {
    if (data.hasOwnProperty(key)) {
    if (data[key].hasOwnProperty("height")) {
    sumHeight += data[key].height;
    count += 1;
    }
    }
    }
    console.log(sumHeight/count); // 182
    ```

    ## Using Object.values() and the reduce() method

    The [Object.values()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values) method returns an array of a given object's **own enumerable property** values, in the same order as that provided by a *for...in* loop (the difference being that a *for-in* loop enumerates properties in the prototype chain as well). For example, *Object.values(data)* will return the following array:

    ```javascript
    [ { height: 176, weight: 87 },
    { height: 190, weight: 103 },
    { height: 180, weight: 98 } ]
    ```

    The [reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value. This method will execute the callback function in different ways, depending on the existence of the optional *initialValue* argument.

    If we don't provide an *initialValue*, the callback function should return an Object for the next call within *reduce()*. For instance:

    ```javascript
    var arr = Object.values(data);
    var sum = (prev, cur) => ({height: prev.height + cur.height});
    var avg = arr.reduce(sum).height / arr.length;
    console.log(avg); // 182
    ```

    And if we provide an *initialValue* of 0, **reduce()** will invoke the callback function differently:

    ```javascript
    var arr = Object.values(data);
    var sum = (accumulator, obj) => accumulator + obj.height;
    var avg = arr.reduce(sum, 0) / arr.length;
    console.log(avg); // 182
    ```

    ## Using Object.keys()

    The [Object.keys()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) method returns an array that contains the names of the own enumerable properties of the object. For instance, *Object.keys(data)* will return the following array:

    ```javascript
    ['Matt', 'Jason', 'Peter']
    ```

    So, let's write the code using that method:

    ```javascript
    var arr = Object.keys(data);
    var getHeight = key => data[key]["height"];
    var avg = arr.reduce((a,c) => a + getHeight(c), 0) / arr.length;
    console.log(avg); // 182
    ```

    ## Using Object.entries()

    The [Object.entries()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) method returns an array that contains the *[key, value]* pairs of the own enumerable properties of the object. Then using *Object.entries(data)* will return the following array:

    ```javascript
    [ [ 'Matt', { height: 176, weight: 87 } ],
    [ 'Jason', { height: 190, weight: 103 } ],
    [ 'Peter', { height: 180, weight: 98 } ] ]
    ```

    Now let's write the code using the array returned by the *Object.entries()* method:

    ```javascript
    var heights = Object.entries(data).map(el => el[1].height);
    var avg2 = heights.reduce((a,c) => a + c) / heights.length;
    console.log(avg2); // 182
    ```

    ### References in MDN

    [1] [for...in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) statement
    [2] [hasOwnProperty()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) method
    [3] [reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) method
    [4] [Object.values()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values) method
    [5] [Object.keys()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) method
    [6] [Object.entries()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) method