【问题标题】:Reduce array of objects in javascript减少javascript中的对象数组
【发布时间】:2020-01-27 16:46:42
【问题描述】:

我在 javascript 中有一个我想减少的对象数组。请参阅下面的代码。 6 位或更多数字的消息已验证,未验证的消息较少。我按组分组。

const myArray = [
  { group: 'groupA', message: 'Text without a number', sl: '1A' },
  { group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
  { group: 'groupB', message: 'Text without a number', sl: '1A' },
  { group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
  { group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
  { group: 'groupC', message: 'Text without a number', sl: '1B' },
  { group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
  { group: 'groupC', message: 'Text without a number', sl: '1A' }
];

output = myArray.reduce((acc, line) => {
  let yes = 0;
  let no = 0;

  line.message.match(/\d{6,}/) ? yes++ : no++;

  acc[line.group] = acc[line.group] || {};
  acc[line.group].verified = (acc[line.group].verified || 0) + yes;
  acc[line.group].unverified = (acc[line.group].unverified || 0) + no;
  return acc;
}, {});

console.log('output', output);

但是我希望输出也是一个对象数组,如下所示:

[
  { group: 'groupA', verified: 2, unverified: 1 },
  { group: 'groupB', verified: 1, unverified: 1 },
  { group: 'groupC', verified: 0, unverified: 2 },
  { group: 'groupD', verified: 1, unverified: 0 }
]

我该怎么做?

【问题讨论】:

  • 更改逻辑并使用数组(myArray.reduce((acc, line) => ..., [])),或者之后使用Object.entries() + .map()转换结果
  • 你能提供一些关于你为什么要达到的背景吗?您将已验证和未验证的属性用于/需要什么?
  • 感谢大家的快速回答!我将使用输出作为 d3.js 堆叠条形图的输入,其中包含月度数据。

标签: javascript arrays object reduce


【解决方案1】:

使用数组作为累加器的初始值,在 .reduce 内部,使用 findIndex 检查当前组,如果找到,更新 verifiedunverified 值,否则,插入一个新值:

const myArray = [
  { group: "groupA", message: "Text without a number", sl: "1A" },
  { group: "groupA", message: "Text with a number WO5467829", sl: "1A" },
  { group: "groupB", message: "Text without a number", sl: "1A" },
  { group: "groupA", message: "Text with a number WO5467829", sl: "1A" },
  { group: "groupB", message: "Text with a number WO5467829", sl: "1A" },
  { group: "groupC", message: "Text without a number", sl: "1B" },
  { group: "groupD", message: "Text with a number Tick0127866", sl: "1B" },
  { group: "groupC", message: "Text without a number", sl: "1A" }
];

output = myArray.reduce((acc, line) => {
  let yes = 0;
  let no = 0;

  line.message.match(/\d{6,}/) ? yes++ : no++;

  // check if you have the group in the accumulator
  const ndx = acc.findIndex(e => e.group === line.group);

  // if you have it, manipulate verified and unverified
  if (ndx > -1) {
    acc[ndx].verified = (acc[ndx].verified || 0) + yes;
    acc[ndx].unverified = (acc[ndx].unverified || 0) + no;
  } else {
    // insert a new entry instead
    acc.push({
      group: line.group,
      verified: yes,
      unverified: no
    });
  }

  return acc;
}, []); // use an array as the initial value of the accumulator

console.log(output);

【讨论】:

    【解决方案2】:

    您可以使用Object.entries()Object.keys() 简单地扩展您的解决方案/输出以获得实际所需的输出。我将使用Object.entries()

    const myArray = [
      { group: 'groupA', message: 'Text without a number', sl: '1A' },
      { group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
      { group: 'groupB', message: 'Text without a number', sl: '1A' },
      { group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
      { group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
      { group: 'groupC', message: 'Text without a number', sl: '1B' },
      { group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
      { group: 'groupC', message: 'Text without a number', sl: '1A' }
    ];
    
    output = myArray.reduce((acc, line) => {
      let yes = 0;
      let no = 0;
    
      line.message.match(/\d{6,}/) ? yes++ : no++;
    
      acc[line.group] = acc[line.group] || {};
      acc[line.group].verified = (acc[line.group].verified || 0) + yes;
      acc[line.group].unverified = (acc[line.group].unverified || 0) + no;
      return acc;
    }, {});
    
    console.log('output', output);
    
    const actualOutput = Object.entries(output).map(([group, value]) => ({group, ...value }));
    
    console.log(actualOutput);

    【讨论】:

      【解决方案3】:

      我忍不住对您的代码进行了一点重构。那就是说。我做了什么:

      • 使用数组 ([]) 启动累加器
      • 如果尚未初始化,则将组推送到数组中
      • 增加 verifiedunverified 取决于您的测试是否失败

      const myArray = [
        { group: "groupA", message: "Text without a number", sl: "1A" },
        { group: "groupA", message: "Text with a number WO5467829", sl: "1A" },
        { group: "groupB", message: "Text without a number", sl: "1A" },
        { group: "groupA", message: "Text with a number WO5467829", sl: "1A" },
        { group: "groupB", message: "Text with a number WO5467829", sl: "1A" },
        { group: "groupC", message: "Text without a number", sl: "1B" },
        { group: "groupD", message: "Text with a number Tick0127866", sl: "1B" },
        { group: "groupC", message: "Text without a number", sl: "1A" }
      ];
      
      output = myArray.reduce((acc, line) => {
        if( acc.findIndex(e => e.group === line.group) === -1 ) {
        	acc.push({
            group: line.group,
            verified: 0,
            unverified: 0
          });
        }
        
        let group = acc.find(e => e.group === line.group);
      
        if( line.message.match(/\d{6,}/) )
        	group.verified++;
        else
        	group.unverified++;
      
        return acc;
      }, []);
      
      console.log(output);

      【讨论】:

        【解决方案4】:

        groupprop 放入您的帐户中。 然后使用Object.values函数返回一个对象的值。

        const myArray = [
          { group: 'groupA', message: 'Text without a number', sl: '1A' },
          { group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
          { group: 'groupB', message: 'Text without a number', sl: '1A' },
          { group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
          { group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
          { group: 'groupC', message: 'Text without a number', sl: '1B' },
          { group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
          { group: 'groupC', message: 'Text without a number', sl: '1A' }
        ];
        
        output = myArray.reduce((acc, line) => {
          let yes = 0;
          let no = 0;
        
          line.message.match(/\d{6,}/) ? yes++ : no++;
        
          acc[line.group] = acc[line.group] || {};
          acc[line.group].group = line.group;
          acc[line.group].verified = (acc[line.group].verified || 0) + yes;
          acc[line.group].unverified = (acc[line.group].unverified || 0) + no;
          return acc;
        }, {});
        
        console.log('output', Object.values(output));

        【讨论】:

        • 有人似乎对所有答案都投了反对票。
        • 可能只是对回答没有尝试的问题的惩罚。但我认为 OP 的代码足够接近,这不是“为我编写代码”的问题。
        • @Barmar 这个尝试就够了。与我通常看到的这类问题相比,我的意思是太多了。
        • @MaheerAli 没错。 reduce 代码是最难的部分。
        • 谢谢,不是我投反对票,对帮助感到满意
        【解决方案5】:

        您可以在Object.entries 上使用map()。我还在reduce 方法中重构了你的代码

        const myArray = [
          { group: 'groupA', message: 'Text without a number', sl: '1A' },
          { group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
          { group: 'groupB', message: 'Text without a number', sl: '1A' },
          { group: 'groupA', message: 'Text with a number WO5467829', sl: '1A' },
          { group: 'groupB', message: 'Text with a number WO5467829', sl: '1A' },
          { group: 'groupC', message: 'Text without a number', sl: '1B' },
          { group: 'groupD', message: 'Text with a number Tick0127866', sl: '1B' },
          { group: 'groupC', message: 'Text without a number', sl: '1A' }
        ];
        
        let output = myArray.reduce((acc, line) => {
          acc[line.group] = acc[line.group] || {verified: 0, unverified: 0};
          if(line.message.match(/\d{6,}/)){
            acc[line.group].verified++
          }
          else{
            acc[line.group].unverified++
          }
        
          return acc;
        }, {});
        
        output = Object.entries(output).map(([k, v]) => ({group: k, ...v}))
        
        console.log('output', output);

        【讨论】:

        • 有人似乎对这里的所有答案都投了反对票。
        【解决方案6】:

        像这样将 reduce 与正则表达式测试结合使用 -

        const myArray = [{
            group: 'groupA',
            message: 'Text without a number',
            sl: '1A'
          },
          {
            group: 'groupA',
            message: 'Text with a number WO5467829',
            sl: '1A'
          },
          {
            group: 'groupB',
            message: 'Text without a number',
            sl: '1A'
          },
          {
            group: 'groupA',
            message: 'Text with a number WO5467829',
            sl: '1A'
          },
          {
            group: 'groupB',
            message: 'Text with a number WO5467829',
            sl: '1A'
          },
          {
            group: 'groupC',
            message: 'Text without a number',
            sl: '1B'
          },
          {
            group: 'groupD',
            message: 'Text with a number Tick0127866',
            sl: '1B'
          },
          {
            group: 'groupC',
            message: 'Text without a number',
            sl: '1A'
          }
        ];
        
        const numberRegex = /[0-9]{6}/;
        
        const res = Object.values(myArray.reduce((acc, curr) => {
          const { group, message } = curr;
          const isPhoneVerified = numberRegex.test(message);
        
          if (!acc[group] && isPhoneVerified) {
            acc[group] = { group: group, verified: 1, unverified: 0 };
          } else if (!acc[group] && !isPhoneVerified) {
            acc[group] = { group: group, verified: 0, unverified: 1 };
          } else if (acc[group] && isPhoneVerified) {
            acc[group].verified += 1;
          } else if (acc[group] && !isPhoneVerified) {
            acc[group].unverified += 1;
          }
        
          return acc;
        
        }, {}));
        
        console.log(res);

        【讨论】:

          猜你喜欢
          • 2018-09-01
          • 2018-09-25
          • 2021-04-02
          • 2020-12-30
          • 1970-01-01
          • 2019-03-26
          • 2017-05-09
          • 2018-01-28
          相关资源
          最近更新 更多