Javascript 使用 lodash 展平嵌套对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42645376/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:19:05  来源:igfitidea点击:

flatten nested object using lodash

javascriptecmascript-6lodash

提问by Giala Jefferson

flatten, flattenDeep or flattenDepth of lodash only accept array. How to flatten nested object?

lodash 的 flatten、flattenDeep 或 flattenDepth 只接受数组。如何展平嵌套对象?

var data = {
  "dates": {
    "expiry_date": "30 sep 2018",
    "available": "30 sep 2017",
    "min_contract_period": [{
      "id": 1,
      "name": "1 month",
      "value": false
    }, {
      "id": 2,
      "name": "2 months",
      "value": true
    }, {
      "id": 3,
      "name": "3 months",
      "value": false
    }]
  },
  "price": {
    "curreny": "RM",
    "min": 1500,
    "max": 2000
  }
}

I want nested property to be the first level, like expiry_date should be level 1, not within dates, and I think dates should be gone, it's not needed anymore. I can do it manually, use map() but I'm looking to use lodash to ease the task.

我希望嵌套属性是第一级,比如 expiry_date 应该是 1 级,而不是在日期内,我认为日期应该消失,不再需要了。我可以手动完成,使用 map() 但我希望使用 lodash 来简化任务。

回答by RaR

One of the easiest solutions would be, merging the nested object with parent,

最简单的解决方案之一是,将嵌套对象与父对象合并,

_.merge(data, data.dates);

This will bring all data.datesproperty into data. Then delete data.dates

这会将所有data.dates属性带入data. 然后删除data.dates

delete data.dates

回答by T.Chmelevskij

ES6 version:

ES6版本:

var data = {
  "dates": {
    "expiry_date": "30 sep 2018",
    "available": "30 sep 2017",
    "min_contract_period": [{
      "id": 1,
      "name": "1 month",
      "value": false
    }, {
      "id": 2,
      "name": "2 months",
      "value": true
    }, {
      "id": 3,
      "name": "3 months",
      "value": false
    }]
  },
  "price": {
    "curreny": "RM",
    "min": 1500,
    "max": 2000
  }
};

var {dates: {expiry_date, ...dates}, ...rest} = data;
var flatData = {dates, expiry_date, ...rest}
console.log(flatData)

One thing to note is that you have to be careful with deeply nested destructuting. In this example if data.datesis undefinedand you'll try to destructure it, error will be thrown.

需要注意的一件事是,您必须小心深度嵌套的解构。在这个例子中,如果data.datesundefined并且你将尝试解构它,则会抛出错误。

回答by Yosvel Quintero Arguelles

You can .merge()the result of .get()and _.pick():

你可以.merge()结果.get()_.pick()

var data = {"dates": {"expiry_date": "30 sep 2018","available": "30 sep 2017","min_contract_period": [{"id": 1,"name": "1 month","value": false}, {"id": 2,"name": "2 months","value": true}, {"id": 3,"name": "3 months","value": false}]},"price": {"curreny": "RM","min": 1500,"max": 2000}},
    result = _.merge(_.get(data, 'dates'), _.pick(data, 'price'));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

回答by Andrey

this flattens object with nested objects and arrays of any depth. keys in resulting object are full paths to properties in input object

这会使用嵌套对象和任何深度的数组来展平对象。结果对象中的键是输入对象中属性的完整路径

public static flattenObject(o: any, prefix?: string, result?: any): any {

    prefix = prefix ? prefix : '';
    result = result ? result : {};

    if (_.isString(o) || _.isNumber(o) || _.isBoolean(o)) {
        result[prefix] = o;
        return result;
    }

    if (_.isArray(o) || _.isPlainObject(o)) {
        for (let i in o) {

            let pref = prefix;
            if (_.isArray(o)) {
                pref = pref + `[${i}]`;
            } else {
                if (_.isEmpty(prefix)) {
                    pref = i;
                } else {
                    pref = prefix + '.' + i;
                }
            }

            Utils.flattenObject(o[i], pref, result);
        }
        return result;
    }


    return result;
}

回答by Vincent

From Andrey's answer

来自安德烈回答

function flattenObject(o, prefix = '', result = {}, keepNull = true) {
  if (_.isString(o) || _.isNumber(o) || _.isBoolean(o) || (keepNull && _.isNull(o))) {
    result[prefix] = o;
    return result;
  }

  if (_.isArray(o) || _.isPlainObject(o)) {
    for (let i in o) {
      let pref = prefix;
      if (_.isArray(o)) {
        pref = pref + `[${i}]`;
      } else {
        if (_.isEmpty(prefix)) {
          pref = i;
        } else {
          pref = prefix + '.' + i;
        }
      }
      flattenObject(o[i], pref, result, keepNull);
    }
    return result;
  }
  return result;
}