对于一组对象,我想找到一个和相同 属性 的不同值的频率,但想为每个项目写入特定计数

For an array of objects I want to find the frequency of different values for one and the same property but want to write specific counts to each item

我有一个包含键和值的对象数组,但有时特定键的值不同。我想找到同一个 属性 名称的不同值的频率。示例数据结构可能如下所示...

var input = [{
  "DPM": "Financing",
  "Tracking_Block": "Capabilities",
  "assessment_field": "channel_availability",
  "assessment_field_values": "Yes",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Capabilities",
  "assessment_field": "channel_availability",
  "assessment_field_values": "No",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "Lead on all comms",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "In buyflow marketing",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "Financing as option at checkout",
  "Field_Type": "Dropdown",
}];

找到所有 属性 值特定计数后,我想以这种方式更改与特定计数相关的每个原始数组项,使其具有额外的 Count 字段每个相关的 属性 和值计数。

计算以下项目属性的不同值的频率...DPMTracking_Blockassessment_field...然后上面的原始示例数据将变为 。 ..

[{
  "DPM": "Financing",
  "Tracking_Block": "Capabilities",
  "assessment_field": "channel_availability",
  "assessment_field_values": "Yes",
  "Field_Type": "Dropdown",
  "DPM_Count": 5,
  "Tracking_Block_Count": 2,
  "assessment_field_Count": 2,
}, {
  "DPM": "Financing",
  "Tracking_Block": "Capabilities",
  "assessment_field": "channel_availability",
  "assessment_field_values": "No",
  "Field_Type": "Dropdown",
  "DPM_Count": 5,
  "Tracking_Block_Count": 2,
  "assessment_field_Count": 2,
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "Lead on all comms",
  "Field_Type": "Dropdown",
  "DPM_Count": 5,
  "Tracking_Block_Count": 3,
  "assessment_field_Count": 3,
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "In buyflow marketing",
  "Field_Type": "Dropdown",
  "DPM_Count": 5,
  "Tracking_Block_Count": 3,
  "assessment_field_Count": 3,
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "Financing as option at checkout",
  "Field_Type": "Dropdown",
  "DPM_Count": 5,
  "Tracking_Block_Count": 3,
  "assessment_field_Count": 3,
}]

下面是我尝试进行分组和计数的代码。

const result = Object.values(input.reduce( (acc,i) => {
    const key = i.DPM+ i. Tracking_Block + i. assessment_field;
    if(!acc[key])
       acc[key] = {...i, assessment_field_values: [i. assessment_field_values] }
    else
       acc[key]. assessment_field_values.push(i. assessment_field_values);
    return acc;
 },{}));

一个好的方法是确定任务并分别执行它们。

因此,首先要弄清楚一个或多个 property/ies do/es 的相同值出现的频率。

这通常可以通过可配置的 reduce 任务来解决,该任务读取和处理 属性 列表并计算所有属性的值。

function collectEntryCounts(config, item) {
  const { propertyList, counts } = config;

  // custom list of property names whose frequencies have to be counted.
  propertyList.forEach(propertyName => {

    // if the currently processed item features
    // one of the specified property names ...
    if (propertyName in item) {

      // ... get the property name specific count index
      // or create it in case it does not yet exist and ...
      const countIndex = counts[propertyName] || (counts[propertyName] = {});

      // ... get the current array item's property value ... 
      const propertyValue = item[propertyName];

      // ... which will be used as key for the property value specific count.
      if (propertyValue in countIndex) {

        countIndex[propertyValue]++;
      } else {
        countIndex[propertyValue] = 1;
      }
    }
  });

  return config;
}

var input = [{
  "DPM": "Financing",
  "Tracking_Block": "Capabilities",
  "assessment_field": "channel_availability",
  "assessment_field_values": "Yes",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Capabilities",
  "assessment_field": "channel_availability",
  "assessment_field_values": "No",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "Lead on all comms",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "In buyflow marketing",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "Financing as option at checkout",
  "Field_Type": "Dropdown",
}];

console.log(
  'property value counts index ...',
  input.reduce(collectEntryCounts, {

    propertyList: ['DPM', 'Tracking_Block', 'assessment_field'],
    counts: {},

  }).counts
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

在第二步内,现在可以 alter/mutate 原始数组的每一项,方法是向其添加键值特定计数。

这也将通过通用实现来完成,例如... addEntryCountsFromBoundConfig ...这是一个 forEach task with a configuration bound to it as the forEach's thisArgs 参数。

配置对象本身是 运行 collectEntryCounts 之前的 reduce 任务的结果。

function collectEntryCounts(config, item) {
  const { propertyList, counts } = config;

  // custom list of property names whose frequencies have to be counted.
  propertyList.forEach(propertyName => {

    // if the currently processed item features
    // one of the specified property names ...
    if (propertyName in item) {

      // ... get the property name specific count index
      // or create it in case it does not yet exist and ...
      const countIndex = counts[propertyName] || (counts[propertyName] = {});

      // ... get the current array item's property value ... 
      const propertyValue = item[propertyName];

      // ... which will be used as key for the property value specific count.
      if (propertyValue in countIndex) {

        countIndex[propertyValue]++;
      } else {
        countIndex[propertyValue] = 1;
      }
    }
  });

  return config;
}

function addEntryCountsFromBoundConfig(item) {
  const { propertyList, counts } = this; // `this` equals the bound config.

  propertyList.forEach(propertyName => {

    // if the currently processed item features one of the specified property
    // names and if the property name specific count index does exist too ...
    if ((propertyName in item) && counts[propertyName]) {

      // ... assign this count index from the bound config-properties and ...
      const countIndex = counts[propertyName];

      // ... do mutate the currently processed item by creating
      // the property specific count field and assigning its value.
      item[propertyName + '_Count'] = countIndex[item[propertyName]];
    }
  });
} 

var input = [{
  "DPM": "Financing",
  "Tracking_Block": "Capabilities",
  "assessment_field": "channel_availability",
  "assessment_field_values": "Yes",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Capabilities",
  "assessment_field": "channel_availability",
  "assessment_field_values": "No",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "Lead on all comms",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "In buyflow marketing",
  "Field_Type": "Dropdown",
}, {
  "DPM": "Financing",
  "Tracking_Block": "Awareness",
  "assessment_field": "Monthly_price_visibility",
  "assessment_field_values": "Financing as option at checkout",
  "Field_Type": "Dropdown",
}];

input.forEach(
  // the callback function.
  addEntryCountsFromBoundConfig,

  // the this context bound to the above callback.
  input.reduce(collectEntryCounts, {
    propertyList: ['DPM', 'Tracking_Block', 'assessment_field'],
    counts: {},
  })
);
console.log('mutated `input` array ...', input);
.as-console-wrapper { min-height: 100%!important; top: 0; }