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

前端 未结 10 954
梦毁少年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));

提交回复
热议问题