Группа объектов массива с одинаковым ключом в javascript не работает

#javascript #node.js #arrays #ecmascript-6

#javascript #node.js #массивы #ecmascript-6

Вопрос:

У меня есть следующий массив объектов.

 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"
    }
    ];
  

Мне нужно объединить объект массива, имеющий тот же ключ идентификатора пользователя, и ожидает следующего вывода.

 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);
  

Вместо actualUserID я ожидаю userId в ответе. Также как мы можем поместить эти данные в bpAlertData. Итак, может ли кто-нибудь помочь мне с этим, так как я застрял с этим надолго. Любая помощь была бы очень признательна.

Ответ №1:

Вы могли бы сгруппировать с идентификатором и получить массив пациентов.

 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; }  

Комментарии:

1. Я не ожидаю, что actualUserID в результате. Итак, как мы можем сделать это лучше?

2. Не могли бы вы сообщить мне, пожалуйста, цель actualUserID: userId ?

3. это переименование деструктурированного свойства: присвоение новым именам переменных

Ответ №2:

Вы можете использовать функцию 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; }  

Комментарии:

1. Не могли бы вы сообщить мне, почему мы использовали actualUserID: userId внутри метода reduce? Я не понял, в чем дело

2. @Vishnu это называется назначением деструктурирования, я использовал этот способ, потому что a хотел создать объекты с желаемым именем свойства.

Ответ №3:

Подход

Вы могли бы сгруппировать элемент по 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()

Разрушающее назначение

Синтаксис распространения (…)

Комментарии:

1. Не могли бы вы, пожалуйста, объяснить часть else? acc[actualUserID] = [el] Я не понял, что касается []

2. @Vishnu это инициализация массива с одним элементом, вот el

3. Можете ли вы дать какую-нибудь ссылку на использование этого? Тем не менее, я в замешательстве относительно обозначения квадратных скобок 🙂

4. @Vishnu: это просто массив developer.mozilla.org/en-US/docs/Web/JavaScript/Reference /…