Best way to flatten JS object (keys and values) to a single depth array

前端 未结 10 792
梦毁少年i
梦毁少年i 2020-12-05 05:10

I have written this small function to get all keys and values of an object and store them into an array. The object might contain arrays as values...

Object {

相关标签:
10条回答
  • 2020-12-05 05:41

    The function below will flatten an object to the specified depth. This function uses a loop rather than recursion. You can choose how child property keys are named, the default is 'parent.child'. The result is an array of [key, value] arrays, like Object.entries(). It requires lodash for isPlainObject and partition(), though you could write your own isPlainObject, partition functions if you wanted to remove the dependency.

    /**
     * Returns an array containing the properties of the given Object in the same format
     * as Object.entries(). Goes through child objects to the specified depth, 
     * flattening the properties and prefixing child keys with a parent key names.
     * @param {Object} object to retrieve property values for
     * @param {Number} maxDepth the maximum number of times to look at properties of
     * properties of the given object.
     * Set to 1 to only retrieve the property values of the given object, 2 to get
     * properties and sub-properties etc.
     * @param {Function} keyPrefixer a function that takes a parent object name, and
     * a child object name and returns a string representing the combined name.
     * @returns {Array} containing the properties and child properties of the given object.
     * Each property is returned as an array [key, value]. 
     * Returns an empty array if object is null, undefined, not-an-object, or empty.
     */
    const flattenEntries = (
      object,
      maxDepth = 2,
      keyPrefixer = (parentKey, childKey) => `${parentKey}.${childKey}`) => {
    
      if (!object || !_.isPlainObject(object)) {
        return [];
      }
    
      // make maxDepth >= 1
      maxDepth = Math.max(1, Math.abs(maxDepth));
    
      const entryIsNotAnObject = ([key, val]) => !_.isPlainObject(val);
    
      let [simpleProperties, childObjects] = _.partition(Object.entries(object), entryIsNotAnObject);
    
      let result = simpleProperties;
    
      for (let depth = 1; depth < maxDepth; depth++) {
    
        for (let [childObjectKey, childObject] of childObjects) {
          const entries = Object.entries(childObject);
          const addParentPrefixToKey = ([key, val]) => [keyPrefixer(childObjectKey, key), val];
          const prefixedEntries = entries.map(addParentPrefixToKey);
          [simpleProperties, childObjects] = _.partition(prefixedEntries, entryIsNotAnObject);
          result = result.concat(simpleProperties);
        }
      }
    
      return result;
    };
    
    const test = {
      a: 'one',
      b: {
        c: 'three',
        d: {
          e: {
            f: ['six', 'six'],
            g: 7
          }
        }
      }
    };
    
    console.log(flattenEntries(test, 10));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

    0 讨论(0)
  • 2020-12-05 05:46

    You can skip the inner loop if you have to push contents of an array to another array. See if this helps --

    function flattenObject(obj) {
    // Returns array with all keys and values of an object
    var array = [];
    $.each(obj, function (key, value) {
        array.push(key);
        if ($.isArray(value)) {
            Array.prototype.push.apply(array, value);
        }
        else {
            array.push(value);
        }
    });
    
    return array;
    }
    var obj = {"key1" : [1,3,3],"key2" : "val", "key3":23};
    var output = flattenObject(obj);
    console.log(output);
    

    Fiddle Link -- https://jsfiddle.net/0wu5z79a/1/

    EDIT : This solution is valid only for your scenario where you know that the nesting is till one level only else you need to have some recursion for deep inner objects.

    0 讨论(0)
  • 2020-12-05 05:48

    I needed something really simple and here is a one-liner I came up with:

    function flatten(obj){
      return Object.values(obj).flat()
    }
    

    Obviously, this is subject to your browser/JS env supporting this syntax. Here is a working example.

    const flatten=(obj)=>Object.values(obj).flat()
    
    const x={x:[1,2,3],y:[4,5,6,7]}
    
    console.log(flatten(x))

    0 讨论(0)
  • 2020-12-05 05:48

    If you're feeling really lazy then you can make use of the popular NPM library flat.

    Example (from their docs)

    var flatten = require('flat')
    
    flatten({
        key1: {
            keyA: 'valueI'
        },
        key2: {
            keyB: 'valueII'
        },
        key3: { a: { b: { c: 2 } } }
    })
    
    // {
    //   'key1.keyA': 'valueI',
    //   'key2.keyB': 'valueII',
    //   'key3.a.b.c': 2
    // }
    
    0 讨论(0)
提交回复
热议问题