使用lodash获取嵌套值

时间:2019-06-24 20:52:53

标签: javascript object lodash

我正在尝试通过给定键从对象中检索嵌套值。我已经使其通过两个简单的forEach循环工作,但我想使用一种更具功能性的方法来解决此问题。

这是到目前为止我得到的代码:

const object = {
  screen: {
    '[data-id="123"]': {
      'font-family': 'Arial',
    },
    '[data-id="456"]': {
      'background-color': 'red',
      'font-family': 'Comic Sans',
    },
  },
};

const prop = 'font-family';
const props = [];

forEach(object, (selectors) => {
  forEach(selectors, (selector) => {
    if (prop in selector) {
      props.push(selector[prop]);
    }
  });
});

console.log(props);

在这种情况下,该函数返回一个字体家族数组(由prop const表示)。

我希望使用mapreduce之类的lodash函数,但我真的不知道从哪里开始。

谢谢。

2 个答案:

答案 0 :(得分:1)

由于这是一个嵌套对象,因此它实际上取决于您要如何解决。如果以嵌套方式使用地图,则最终将得到嵌套数组。为了匹配您的输出,可以将嵌套数组展平。

_.flatten(_.map(object, (prop) => _.map(prop, (nestedProp) => nestedProp['font-family'])));

但是,如果您不想使用reduce而不是flatten,则可以从数组中减少嵌套数组。

_.reduce(_.map(object, (prop) => _.map(prop, (nestedProp) => nestedProp['font-family'])),(a, b) => [...a, ...b]);

在这一点上,我认为可读性受到了一些打击。如您所见,嵌套的地图函数可能会变得凌乱。

答案 1 :(得分:0)

您可以使用_.flatMap()递归地迭代对象/数组,并使用等于prop的键来收集所有值:

const collect = (prop, obj) =>
  _.flatMap(obj, (v, k) => {
    if(k === prop) return v;
    
    return _.isObject(v) ? collect(prop, v) : [];
  });

const object = {
  screen: {
    '[data-id="123"]': {
      'font-family': 'Arial',
    },
    '[data-id="456"]': {
      'background-color': 'red',
      'font-family': 'Comic Sans',
    },
  },
};

const result = collect('font-family', object);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

在香草JS中,您可以使用Object.entries()Array.flatMap()

const collect = (prop, obj) =>
  Object.entries(obj).flatMap(([k, v]) => {
    if(k === prop) return v;
    
    return typeof v === 'object' && v !== null ? collect(prop, v) : [];
  });

const object = {
  screen: {
    '[data-id="123"]': {
      'font-family': 'Arial',
    },
    '[data-id="456"]': {
      'background-color': 'red',
      'font-family': 'Comic Sans',
    },
  },
};

const result = collect('font-family', object);

console.log(result);