【问题标题】:groupBy and value as keygroupBy 和 value 作为 key
【发布时间】:2020-11-19 10:13:13
【问题描述】:

我有以下数据:

var groups = {
  0: { 'GroupID': 1, 'AttributeID': 'Agitator', 'Value': 'No' },
  1: { 'GroupID': 1, 'AttributeID': 'ATG', 'Value': 'Custodian' },
  2: { 'GroupID': 1, 'AttributeID': 'Heating Coil', 'Value': 'Mild Steel' },
  3: { 'GroupID': 2, 'AttributeID': 'Agitator', 'Value': 'Yes' },
  4: { 'GroupID': 2, 'AttributeID': 'ATG', 'Value': 'Non Custodian' },
  5: { 'GroupID': 2, 'AttributeID': 'Heating Coil', 'Value': 'Mild Steel' },
};

我想按 GroupID 对数据进行分组,并将其中一个值用作另一个值的键。预期结果如下。这可以实现吗?

var data = {
  0: { 'GroupID': 1, 'Agitator': 'No', 'ATG': 'Custodian', 'Heating Coil': 'Mild Steel' },
  1: { 'GroupID': 2, 'Agitator': 'Yes', 'ATG': 'Non Custodian', 'Heating Coil': 'Mild Steel' }
};

到目前为止,我尝试过的如下。我不知道如何将一个值作为另一个值的键。

_.chain(groups).groupBy('GroupID').map((value, key) => {
    return {
      GroupID: key,
      AttributeID: _.map(value, 'AttributeID'),
      Value: _.map(value, 'Value')
    }
}).value();

结果如下所示。

var data = {
      0: { 'GroupID': 1, 'AttributeID': ['Agitator', 'ATG', 'Heating Coil'], 'Value': ['No', 'Custodian', 'Mild Steel'] },
      1: { 'GroupID': 2, 'AttributeID': ['Agitator', 'ATG', 'Heating Coil'], 'Value': ['Yes', 'Non Custodian', 'Mild Steel'] }
    };

感谢任何帮助。

【问题讨论】:

  • 您是否尝试过解决您自己的问题,如果有,它是什么样的?您咨询过哪些来源?有没有让您感到困惑的文档?
  • 编辑了我的问题以包括我迄今为止尝试过的内容。谢谢。

标签: lodash underscore.js


【解决方案1】:

您已经非常接近解决自己的问题了。做得好!让我们把它分成几部分,看看缺少什么。

您正确地确定了_.groupBy 是您收集具有相同GroupID 的对象所需要的。

var grouped = _.groupBy(groups, 'GroupID');
// { '1':
//    [ { GroupID: 1, AttributeID: 'Agitator', Value: 'No' },
//      { GroupID: 1, AttributeID: 'ATG', Value: 'Custodian' },
//      { GroupID: 1, AttributeID: 'Heating Coil', Value: 'Mild Steel' } ],
//   '2':
//    [ { GroupID: 2, AttributeID: 'Agitator', Value: 'Yes' },
//      { GroupID: 2, AttributeID: 'ATG', Value: 'Non Custodian' },
//      { GroupID: 2, AttributeID: 'Heating Coil', Value: 'Mild Steel' } ] }

您还正确地将 _.map 标识为可让您跨对象数组收集特定属性值的函数。

var firstGroupAttributes = _.map(grouped['1'], 'AttributeID');
// [ 'Agitator', 'ATG', 'Heating Coil' ]

您编写的为每个组构造最终对象的函数为第一组生成了以下对象:

{
    'GroupID': 1,
    'AttributeID': ['Agitator', 'ATG', 'Heating Coil'],
    'Value': ['No', 'Custodian', 'Mild Steel']
}

为了方便,AttributeIDValue 属性的顺序相同,所以Value 数组的第一个元素对应AttributeID 数组的第一个元素,第二个到第二个,以此类推. Underscore 有一个名为_.object1 的函数,它可以接受这样一对数组并返回一个对象,其中第一个数组的每个元素命名一个属性,第二个数组的对应元素提供它的值:

_.object(['Agitator', 'ATG'], ['No', 'Custodian']);
// { Agitator: 'No',
//   ATG: 'Custodian', }

处理完属性及其值后,现在我们只需要将GroupID 添加到对象中。有几个类似但略有不同的函数可用于此目的,例如_.extend_.defaults

_.extend({ a: 1 }, { b: 2 });
// { a: 1, b: 2 }

将这些成分放在一起,我们映射到grouped 的函数可能看起来像这样:

function mergeGroup(value, key) {
    var attributes = _.map(value, 'AttributeID');
    var values = _.map(value, 'Value');
    return _.chain(attributes).object(values).extend({ GroupID: key }).value();
}

如果您像以前一样使用_.map,您将获得一个包含最终对象的数组。

var data = _.chain(groups).groupBy('GroupID').map(mergeGroup).value();
// [ { Agitator: 'No',
//     ATG: 'Custodian',
//     'Heating Coil': 'Mild Steel',
//     GroupID: '1' },
//   { Agitator: 'Yes',
//     ATG: 'Non Custodian',
//     'Heating Coil': 'Mild Steel',
//     GroupID: '2' } ]

或者,您可以使用_.mapObject2 生成一个对象,其中每个键都与GroupID 相同:

var data = _.chain(groups).groupBy('GroupID').mapObject(mergeGroup).value();
// { '1':
//    { Agitator: 'No',
//      ATG: 'Custodian',
//      'Heating Coil': 'Mild Steel',
//      GroupID: '1' },
//   '2':
//    { Agitator: 'Yes',
//      ATG: 'Non Custodian',
//      'Heating Coil': 'Mild Steel',
//      GroupID: '2' } }

1 Lodash 最初从 Underscore 继承了 _.object,但他们添加了一个名为 _.zipObject 的别名,并且在版本 4 中,他们决定从他们的界面中删除原来的名称 _.object。因此,如果使用 Lodash,您必须致电 _.zipObject。 Underscore 的_.object 也可以使用一对数组而不是一对数组;在 Lodash 4 中,您将使用 _.fromPairs 代替。

2_.mapValues 在 Lodash。

【讨论】:

  • 您好 Julian,非常感谢您的帮助和花时间解释您的解决方案。它就像一个魅力!赞赏!
猜你喜欢
  • 1970-01-01
  • 2015-10-12
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 2020-02-23
  • 1970-01-01
相关资源
最近更新 更多