我得到的数据是这样的

[
    {
        "channel_number": 1,
        "id_channel": "св-1312",
        "consumption": 1231,
        "date": 01
    },
    {
        "channel_number": 1,
        "id_channel": "св-1312",
        "consumption": 1234,
        "date": 02
    },
    {
        "channel_number": 1,
        "id_channel": "св-1312",
        "consumption": 1234,
        "date": 03
    },
    {
        "channel_number": 2,
        "id_channel": "св-1314",
        "consumption": 800,
        "date": 01
    },
    {
        "channel_number": 2,
        "id_channel": "св-1314",
        "consumption": 823,
        "date": 02
    },
    {
        "channel_number": 2,
        "id_channel": "св-1314",
        "consumption": 1233,
        "date": 03
    }
]

我需要使每个日期的数据合并成一个对象.

就像这样:

[
  {
    date: 01,
    channels: [
      {
        channel_number: 1
        consumption: 1000
      },
      {
        channel_number: 2
        consumption: 2000
      }
    ]
  },
  {
    date: 02,
    channels: [
      {
        channel_number: 1
        consumption: 1000
      },
      {
        channel_number: 2
        consumption: 2000
      }
    ]
  },
  ...
]

数据来自服务器,所以可能会有更多的日期和渠道.

我做了以下操作,但它没有给我需要的东西:

let newArr = arr.map((el: any, i: any) => {
    return {
      date: el.date,
      channels: [{ channel_number: el.channel_number, consumption: el.consumption }],
    };
  });

我试过其他方法,但不起作用.只是第一次需要这样的转变,但我没有经验

请帮帮我.

推荐答案

你可以用Array.prototype.reduce():

const input = [{
    "channel_number": 1,
    "id_channel": "св-1312",
    "consumption": 1231,
    "date": 01
  },
  {
    "channel_number": 1,
    "id_channel": "св-1312",
    "consumption": 1234,
    "date": 02
  },
  {
    "channel_number": 1,
    "id_channel": "св-1312",
    "consumption": 1234,
    "date": 03
  },
  {
    "channel_number": 2,
    "id_channel": "св-1314",
    "consumption": 800,
    "date": 01
  },
  {
    "channel_number": 2,
    "id_channel": "св-1314",
    "consumption": 823,
    "date": 02
  },
  {
    "channel_number": 2,
    "id_channel": "св-1314",
    "consumption": 1233,
    "date": 03
  }
];

const output = input.reduce((acc, item) => {
  // 1. You check whether the accumulator already contains an object
  //    with the same date of the item you are currently considering
  let accItem = acc.find(_item => _item.date === item.date);

  if (accItem) {
    // 2a. if it does, you update that object by pushing into the `channels` array
    //     the data from your item
    accItem.channels.push({
      channel_number: item.channel_number,
      consumption: item.consumption
    });
  } else {
    // 2b. if it does NOT, you create a new object from the item
    //     and you push it into the accumulator
    acc.push({
      date: item.date,
      channels: [{
        channel_number: item.channel_number,
        consumption: item.consumption
      }]
    })
  }
  
  // 3. finally you return the updater accumulator and repeat point 1 and 2
  //    for the following item in your input array
  return acc
}, []);

console.log(output);

编辑:避免嵌套循环的替代解决方案

实际上,现在我想一想,如果您的输入数组可以包含很多项,那么在Array.prototype.reduce()中使用Array.prototype.find()可能不是最佳的性能解决方案,因为您有嵌套的循环.

尽管它不那么"线性",但此解决方案的性能可能会更好:

const input = [{
    "channel_number": 1,
    "id_channel": "св-1312",
    "consumption": 1231,
    "date": 01
  },
  {
    "channel_number": 1,
    "id_channel": "св-1312",
    "consumption": 1234,
    "date": 02
  },
  {
    "channel_number": 1,
    "id_channel": "св-1312",
    "consumption": 1234,
    "date": 03
  },
  {
    "channel_number": 2,
    "id_channel": "св-1314",
    "consumption": 800,
    "date": 01
  },
  {
    "channel_number": 2,
    "id_channel": "св-1314",
    "consumption": 823,
    "date": 02
  },
  {
    "channel_number": 2,
    "id_channel": "св-1314",
    "consumption": 1233,
    "date": 03
  }
];

const tempObj = input.reduce((obj, item) => {
  if (obj[item.date]) {
    obj[item.date].channels.push({
      channel_number: item.channel_number,
      consumption: item.consumption
    });
  } else {
    obj[item.date] = {
      date: item.date,
      channels: [{
        channel_number: item.channel_number,
        consumption: item.consumption
      }]
    }
  }

  return obj;
}, {});

const output = Object.values(tempObj);

console.log(output);

如果您注意到原来的解决方案在生产中太慢,您可能希望try 这个解决方案,看看情况是否有所改善.

Javascript相关问答推荐

在JavaScript中打开和关闭弹出窗口

如果没有尾随斜线,托管在收件箱中的React/Vite将无法工作

在具有焦点和上下文的d3多线图表中,如何将上下文的刷新限制在特定日期?

当在select中 Select 选项时,我必须禁用不匹配的 Select

在React中获取数据后,如何避免不必要的组件闪现1秒?

Cookie中未保存会话数据

在JavaScript中声明自定义内置元素不起作用

点击按钮一次有文本出现和褪色,而不是点击两次?(html,CSS,JavaScript)

为什么useState触发具有相同值的呈现

如何控制Reaction路由加载器中的错误状态?

编剧如何获得一个div内的所有链接,然后判断每个链接是否都会得到200?

Html文件和客户端存储的相关问题,有没有可能?

如何在ASP.NET中使用Google Charts API JavaScript将条形图标签显示为绝对值而不是负值

React.Development.js和未捕获的ReferenceError:未定义useState

查询参数中的JAVASCRIPT/REACT中的括号

根据一个条件,如何从处理过的数组中移除一项并将其移动到另一个数组?

Nextjs 13.4 Next-Auth 4.2登录(&Quot;凭据&,{});不工作

在FAQ Accodion应用程序中使用React useState时出现问题

是否可以将异步调用与useState(UnctionName)一起使用

如果NetSuite中为空,则限制筛选