根据 ID 对数组数据进行分组

3
通过 API 调用我收到了如下响应。
[
  {
    stationId: "10"
    name: "Jinbaolai"
    group: {id: "18", stationGroupName: "Ali"}
  },
  {
    stationId: "13"
    name: "Stack"
    group: {id: "18", stationGroupName: "Ali"}
  },
  {
    stationId: "20"
    name: "Overflow"
    group: {id: "19", stationGroupName: "Baba"}
  }

]

如您所见,前两条记录属于同一组。我希望将这些数据根据组分组。例如,它应该是这样的:

[
  {
    groupId: "18",
    groupName : "Ali",
    stations : [
                 {
                  stationId: "10",
                  name: "Jinbaolai"
                 },
                 {
                  stationId: "13",
                  name: "Stack"
                 }
               ]

  },
  {
    groupId: "19",
    groupName : "Baba",
    stations : [
                 {
                  stationId: "20",
                  name: "Overflow"
                 },
               ]

  }

]

我希望在我的reducer中实现分组逻辑,同时设置显示在问题开头的完整数据数组。
            case EVC_SUCCESS:
            return {
                ...state,
                chargingStations: action.evcData.chargingStations,
                chargingStationGroups: //This is where my logic should go. ('action.evcData.chargingStations' is the initial data array)
                tableLoading: false
            }

我该怎么做?我尝试使用 filter 但没有成功。

3个回答

4

最好的方法是使用Array.prototype.reduce()

reduce 是一个聚合函数,你可以把一个数组放进去得到单个的返回值。

可能会有一个起始值作为最后一个参数,就像我用的{}。 函数签名为reduce(fn, startingValue),其中 fn 是一个接收两个参数 aggregatecurrentValue 的函数,并在最后返回聚合结果。

const groupData = (data)=> {

    return Object.values(data.reduce((group,n)=>{
    if (!group[n.group.id]){
        group[n.group.id] = {
      groupId:n.group.id,
      groupName: n.group.stationGroupName,
      stations:[]}
    } 
    group[n.group.id].stations.push({
      stationID: n.stationId,
      name: n.name
    })
    return group;
  }, {}))

}

这里是代码编辑器示例。

谢谢。这正是我所需要的! - CraZyDroiD
有一个问题。输出应该是一个数组,但这里却生成了一个对象。如何解决? - CraZyDroiD
1
应该给你的值:Object.values(groupData(data)),请参见https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/values。 - Thomas Junk

1
一个简单的JS算法可以为您完成这个任务。
const list = [
  {
    stationId: "10",
    name: "Jinbaolai",
    group: {id: "18", stationGroupName: "Ali"}
  },
  {
    stationId: "13",
    name: "Stack",
    group: {id: "18", stationGroupName: "Ali"}
  },
  {
    stationId: "20",
    name: "Overflow",
    group: {id: "19", stationGroupName: "Baba"}
  }

];
const groups = {};

list.forEach((item) => {
  const groupId = item.group.id;
  const group = groups[groupId] || {groupId: groupId, groupName: item.group.stationGroupName, stations: []};

  group.stations.push({stationId: item.stationId, name: item.name});
  groups[groupId] = group;
});

const groupedArray = Object.keys(groups).map((groupId) => groups[groupId]);

console.log(groupedArray); // This will be the output you want

0

我认为链式调用多个函数会起作用。

const stations = [
  {
    "stationId": 10,
    "name": "Jinbaolai",
    "group": {"id": "18", "stationGroupName": "Ali"}
  },
  {
    "stationId": 13,
    "name": "Stack",
    "group": {"id": 18, "stationGroupName": "Ali"}
  },
  {
    "stationId": 20,
    "name": "Overflow",
    "group": {"id": "19", "stationGroupName": "Baba"}
  }
]
const groups = _.chain(stations)
.groupBy((station) => { return station.group.id })
.map((values, key) => { 
  return {
    "groupId": _.first(values).group.id,
    "groupName": _.first(values).group.id,
    "stations": _.map(values,(value)=>{ return { "stationId": value.stationId, "name": value.name   } })
  }
})
console.log("groups",groups)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>


虽然这是一个有效的答案:为什么要包含 lodash 来做这样基本的事情呢?如果你不喜欢 JS 的符号,你可以使用 reduce = Function.prototype.call.bind([].reduce),然后你可以写成 reduce([1,2,3], (a,b)=> a+b) - Thomas Junk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接