【问题标题】:Group array objects with same key in javascript is not workingjavascript中具有相同键的组数组对象不起作用
【发布时间】:2020-12-16 10:52:28
【问题描述】:

我有以下对象数组。

let arr = [
 {
  "alerts": {
    "bp": {
      "diaDiff": -20,
      "Notes": null,
      "resolveStatus": "0",
      "sysDiff": 10
    },
    "threshold": {
      "diaHigh": "110",
      "diaLow": "60",
      "sysHigh": "150",
      "sysLow": "90"
    },
    "thresholdBpUnit": "mmHg"
  },
  "measurementDate": 1593934933000,
  "actualUserID ": "11111"
},
{
  "alerts": {
    "bp": {
      "diaDiff": -20,
      "Notes": null,
      "resolveStatus": "0",
      "sysDiff": 10
    },
    "threshold": {
      "diaHigh": "110",
      "diaLow": "60",
      "sysHigh": "150",
      "sysLow": "90"
    },
    "thresholdBpUnit": "mmHg"
  },
  "measurementDate": 1593934933000,
  "actualUserID ": "2222"
},
{
  "alerts": {
    "bp": {
      "diaDiff": 80,
      "Notes": null,
      "resolveStatus": "0",
      "sysDiff": 20
    },
    "threshold": {
      "diaHigh": "120",
      "diaLow": "60",
      "sysHigh": "140",
      "sysLow": "90"
    },
    "thresholdBpUnit": "mmHg"
  },
  "measurementDate": 6593934956000,
  "actualUserID ": "11111"
},
{
  "alerts": {
    "bp": {
      "diaDiff": 400,
      "Notes": null,
      "resolveStatus": "0",
      "sysDiff": 10
    },
    "threshold": {
      "diaHigh": "170",
      "diaLow": "60",
      "sysHigh": "190",
      "sysLow": "90"
    },
    "thresholdBpUnit": "mmHg"
  },
  "measurementDate": 1593934944000,
  "actualUserID ": "2222"
},
{
      "alerts": {
        "bp": {
          "diaDiff": 300,
          "Notes": null,
          "resolveStatus": "0",
          "sysDiff": 10
        },
        "threshold": {
          "diaHigh": "570",
          "diaLow": "60",
          "sysHigh": "190",
          "sysLow": "90"
        },
        "thresholdBpUnit": "mmHg"
      },
      "measurementDate": 8593934989000,
      "actualUserID ": "6666"
    }
    ];

我需要合并具有相同 userID 键的数组对象,并期待以下输出。

let response = {
  "success": true,
  "data": {
      "patient": [
         {
           "userID": "11111", // I need userID not actualUserID 
           "bpAlertData": [
              {
                alerts: { // object },
                measurementDate: 1593934933000
              },
              {
                alerts: { // object },
                measurementDate: 6593934956000
              }
            ]
         },
         {
           "userID": "22222",
           "bpAlertData": [
              {
                alerts: { // object },
                measurementDate: 1593934944000
              },
              {
                alerts: { // object },
                measurementDate: 1593934933000
              }
            ]
         }
       ]
  },
};

我尝试了以下方法,但还是坚持了下来。

arr.forEach((item) => {
  let filteredData = response.data.patient.filter(patient => patient.userID === item.actualUserID);
  if(filteredData.length) {
       const existingIndex = response.data.patient.indexOf(filteredData[0]);
       response.data.patient[existingIndex].bpAlertData = response.data.patient[existingIndex].bpAlertData.concat(item);
  } else {
    response.data.patient.push(item);
  }
});

console.log(response.data.patient);

我期望响应中的不是实际用户 ID,而是用户 ID。此外,我们如何将这些数据推送到 bpAlertData。所以有人可以帮我解决这个问题,因为我已经坚持了很长时间。任何帮助将不胜感激。

【问题讨论】:

    标签: javascript node.js arrays ecmascript-6


    【解决方案1】:

    您可以使用 id 分组并获取一组患者。

    const
        data = [{ alerts: { bp: { diaDiff: -20, Notes: null, resolveStatus: "0", sysDiff: 10 }, threshold: { diaHigh: "110", diaLow: "60", sysHigh: "150", sysLow: "90" }, thresholdBpUnit: "mmHg" }, measurementDate: 1593934933000, actualUserID: "11111" }, { alerts: { bp: { diaDiff: -20, Notes: null, resolveStatus: "0", sysDiff: 10 }, threshold: { diaHigh: "110", diaLow: "60", sysHigh: "150", sysLow: "90" }, thresholdBpUnit: "mmHg" }, measurementDate: 1593934933000, actualUserID: "2222" }, { alerts: { bp: { diaDiff: 80, Notes: null, resolveStatus: "0", sysDiff: 20 }, threshold: { diaHigh: "120", diaLow: "60", sysHigh: "140", sysLow: "90" }, thresholdBpUnit: "mmHg" }, measurementDate: 6593934956000, actualUserID: "11111" }, { alerts: { bp: { diaDiff: 400, Notes: null, resolveStatus: "0", sysDiff: 10 }, threshold: { diaHigh: "170", diaLow: "60", sysHigh: "190", sysLow: "90" }, thresholdBpUnit: "mmHg" }, measurementDate: 1593934944000, actualUserID: "2222" }, { alerts: { bp: { diaDiff: 300, Notes: null, resolveStatus: "0", sysDiff: 10 }, threshold: { diaHigh: "570", diaLow: "60", sysHigh: "190", sysLow: "90" }, thresholdBpUnit: "mmHg" }, measurementDate: 8593934989000, actualUserID: "6666" }],
        patient = Object.values(data.reduce((r, { actualUserID: userID, ...o }) => {
            if (!r[userID]) r[userID] = { userID, bpAlertData: [] };
            r[userID].bpAlertData.push(o);
            return r;
        }, [])),
        response = { success: true, data: { patient } };
    
    console.log(response);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 我不希望实际用户 ID 出现在结果中。那么我们怎样才能让它变得更好呢?
    • 你能告诉我actualUserID: userID的用途吗?
    • 它是对解构属性的重命名:Assigning to new variable names
    【解决方案2】:

    方法

    您可以按userId 对元素进行分组,然后通过该分组进行操作

    const userIdDataMapping = arr.reduce((acc, { actualUserID, ...el }) => {
      if (acc[actualUserID] !== undefined) {
        acc[actualUserID].push(el)
      } else {
        acc[actualUserID] = [el]
      }
      return acc
    }, {})
    
    const res = Object.entries(userIdDataMapping).map(([userId, bpAlertData]) => ({
      userId,
      bpAlertData,
    }))
    

    注意

    • { actualUserID, ...el } 从元素中排除 actualUserId
    • [userId, bpAlertData] 破坏赋值

    完整代码

    let arr = [
      {
        alerts: {
          bp: {
            diaDiff: -20,
            Notes: null,
            resolveStatus: "0",
            sysDiff: 10,
          },
          threshold: {
            diaHigh: "110",
            diaLow: "60",
            sysHigh: "150",
            sysLow: "90",
          },
          thresholdBpUnit: "mmHg",
        },
        measurementDate: 1593934933000,
        actualUserID: "11111",
      },
      {
        alerts: {
          bp: {
            diaDiff: -20,
            Notes: null,
            resolveStatus: "0",
            sysDiff: 10,
          },
          threshold: {
            diaHigh: "110",
            diaLow: "60",
            sysHigh: "150",
            sysLow: "90",
          },
          thresholdBpUnit: "mmHg",
        },
        measurementDate: 1593934933000,
        actualUserID: "2222",
      },
      {
        alerts: {
          bp: {
            diaDiff: 80,
            Notes: null,
            resolveStatus: "0",
            sysDiff: 20,
          },
          threshold: {
            diaHigh: "120",
            diaLow: "60",
            sysHigh: "140",
            sysLow: "90",
          },
          thresholdBpUnit: "mmHg",
        },
        measurementDate: 6593934956000,
        actualUserID: "11111",
      },
      {
        alerts: {
          bp: {
            diaDiff: 400,
            Notes: null,
            resolveStatus: "0",
            sysDiff: 10,
          },
          threshold: {
            diaHigh: "170",
            diaLow: "60",
            sysHigh: "190",
            sysLow: "90",
          },
          thresholdBpUnit: "mmHg",
        },
        measurementDate: 1593934944000,
        actualUserID: "2222",
      },
      {
        alerts: {
          bp: {
            diaDiff: 300,
            Notes: null,
            resolveStatus: "0",
            sysDiff: 10,
          },
          threshold: {
            diaHigh: "570",
            diaLow: "60",
            sysHigh: "190",
            sysLow: "90",
          },
          thresholdBpUnit: "mmHg",
        },
        measurementDate: 8593934989000,
        actualUserID: "6666",
      },
    ]
    
    const userIdDataMapping = arr.reduce((acc, { actualUserID, ...el }) => {
      if (acc[actualUserID] !== undefined) {
        acc[actualUserID].push(el)
      } else {
        acc[actualUserID] = [el]
      }
      return acc
    }, {})
    
    const res = Object.entries(userIdDataMapping).map(([userId, bpAlertData]) => ({
      userId,
      bpAlertData,
    }))
    
    console.log(res)

    参考

    Object.entries()

    Destructing assignment

    Spread syntax (...)

    【讨论】:

    • 您能解释一下其他部分吗? acc[actualUserID] = [el] 我没明白 []
    • @Vishnu 它正在用一个元素初始化一个数组,这里是el
    • 你能提供一些使用这个的参考吗?我仍然对方括号表示法感到困惑:)
    【解决方案3】:

    您可以使用函数Array.prototype.reduce进行分组,使用函数Object.values提取userID分组的对象。

    let arr = [ {  "alerts": {    "bp": {      "diaDiff": -20,      "Notes": null,      "resolveStatus": "0",      "sysDiff": 10    },    "threshold": {      "diaHigh": "110",      "diaLow": "60",      "sysHigh": "150",      "sysLow": "90"    },    "thresholdBpUnit": "mmHg"  },  "measurementDate": 1593934933000,  "actualUserID": "11111"},{  "alerts": {    "bp": {      "diaDiff": -20,      "Notes": null,      "resolveStatus": "0",      "sysDiff": 10    },    "threshold": {      "diaHigh": "110",      "diaLow": "60",      "sysHigh": "150",      "sysLow": "90"    },    "thresholdBpUnit": "mmHg"  },  "measurementDate": 1593934933000,  "actualUserID": "2222"},{  "alerts": {    "bp": {      "diaDiff": 80,      "Notes": null,      "resolveStatus": "0",      "sysDiff": 20    },    "threshold": {      "diaHigh": "120",      "diaLow": "60",      "sysHigh": "140",      "sysLow": "90"    },    "thresholdBpUnit": "mmHg"  },  "measurementDate": 6593934956000,  "actualUserID": "11111"},{  "alerts": {    "bp": {      "diaDiff": 400,      "Notes": null,      "resolveStatus": "0",      "sysDiff": 10    },    "threshold": {      "diaHigh": "170",      "diaLow": "60",      "sysHigh": "190",      "sysLow": "90"    },    "thresholdBpUnit": "mmHg"  },  "measurementDate": 1593934944000,  "actualUserID": "2222"},{      "alerts": {        "bp": {          "diaDiff": 300,          "Notes": null,          "resolveStatus": "0",          "sysDiff": 10        },        "threshold": {          "diaHigh": "570",          "diaLow": "60",          "sysHigh": "190",          "sysLow": "90"        },        "thresholdBpUnit": "mmHg"      },      "measurementDate": 8593934989000,      "actualUserID": "6666"    }    ],        
        obj = { "success": true, "data": {"patient":  Object.values(arr.reduce((a, {alerts, measurementDate, actualUserID: userID}) => {
          (a[userID] || (a[userID] = {bpAlertData: [], userID})).bpAlertData.push({alerts, measurementDate});
          return a;
        }, {}))}};
    
    console.log(obj);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 你能告诉我为什么我们在reduce方法中使用actualUserID: userID 吗?没看懂
    • @Vishnu 这被称为解构赋值,我使用这种方式是因为想要创建具有所需属性名称的对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-29
    • 1970-01-01
    • 2018-01-26
    • 2017-10-24
    • 2021-10-09
    • 2016-01-30
    • 1970-01-01
    相关资源
    最近更新 更多