groupBy 和值作为键

groupBy and value as key

我有以下数据:

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

感谢任何帮助。

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

您正确地确定了 _.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 的函数,它可以接受这样一对数组和 return 一个对象,其中第一个数组的每个元素命名为 属性 并且第二个数组的相应元素提供其值:

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

处理完属性及其值后,现在我们只需将 GroupID 添加到对象。有几个类似但略有不同的函数可用于此目的,例如 _.extend and _.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 中。