使用lodash压平嵌套对象

问题描述 投票:0回答:7

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
  }
}

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

javascript ecmascript-6 lodash
7个回答
20
投票

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

_.merge(data, data.dates);

这会将所有

data.dates
财产带入
data
。然后删除
data.dates

delete data.dates

7
投票

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)

需要注意的一件事是,必须小心深层嵌套的解构。在此示例中,如果

data.dates
undefined
并且您尝试对其进行解构,则会抛出错误。


3
投票

您可以 .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>


2
投票

来自Andrey答案

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;
}

2
投票

如果您正在寻找现有的解决方案,您可以使用名为 flat 的库,如此 lodash github 问题

中所述

1
投票

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

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;
}

1
投票

如果您需要展平整个对象,而不仅仅是其“日期”属性,类似这样的东西应该可以工作,您甚至不需要lodash:

var data = {
  "dates": {
    "expiry_date": "30 sep 2018",
    "available": "30 sep 2017",
    "min_contract_period": [/*...*/]
  },
  "price": {
    "curreny": "RM",
    "min": 1500,
    "max": 2000
  }
};

const flattenedObj = flattenObject(data);
// {
//    "expiry_date": "30 sep 2018",
//    "available": "30 sep 2017",
//    "min_contract_period": [/*...*/],
//    "curreny": "RM",
//    "min": 1500,
//    "max": 2000
// }

function flattenObject(obj) {
  const result = {};

  Object.entries(obj).forEach(([key, val]) => {
    // if object (and not null!), merge it with the resulting object,
    // otherwise just copy the value
    if (val && typeof val === "object")
      Object.assign(result, val);
    else
      result[key] = val;
  });

  return result;
}
© www.soinside.com 2019 - 2024. All rights reserved.