Skip to content
Advertisement

Alternatives to using multiple reduce() functions inside a map() when handling deeply nested array of objects?

I have an object result which has a property records which is an array of objects with a single sample below:

const result = {
  records: [
    {
      keys: ["names", "value", "country", "questions"],
      length: 4,
      _fields: [
        "123ilSE",
        [
          "Longitude:5.1193",
          "Latitude:52.3246",
          "Agreeableness:0.147083333333333",
          "Openness:0.211041666666667",
          "Neuroticism:0.168833333333333",
          "Extraversion:0.150291666666666",
          "Conscientiousness:0.187041666666666",
          "Angry:0.0441711768507957",
          "Fear:0.020498564466834",
          "Joy:0.875858068466186",
          "Sadness:0.0477884039282798",
          "Love:0.00839435961097478",
        ],
        ["Netherlands", "Netherlands"],
        [
          ["Right"],
          ["Student Loan", "None"],
          ["Not at all, i’d rather rent all assets."],
          ["Another benefit"],
          ["Every two weeks", "Yearly a few times"],
          [
            "None",
            "1 to 2 hours",
            "1 to 2 hours",
            "3 hours or more",
            "Less then 1 hour",
          ],
          ["Two to Three Times a Week"],
          [
            "1 to 2 hours",
            "1 to 2 hours",
            "3 hours or more",
            "Less then 1 hour",
          ],
          [
            "1 to 2 hours",
            "1 to 2 hours",
            "3 hours or more",
            "Less then 1 hour",
          ],
          [
            "None",
            "1 to 2 hours",
            "1 to 2 hours",
            "3 hours or more",
            "Less then 1 hour",
          ],
          ["Every two weeks", "Yearly a few times"],
          ["Two to Three Times a Week"],
          ["Every Year"],
          ["Banking & Financial Services", "Unemployed"],
          ["I don't have a car"],
          ["Netherlands", "Netherlands"],
          ["3 - 4 persons"],
          ["Maybe, it depends if nothing betters comes up"],
          ["Desktop"],
          [],
          ["I don't drive or have a car"],
          [
            "E, I can be found on social media platforms and maintain my profile but do little else.",
          ],
          ["None", "Healthcare Insurance"],
          ["None", "Hockey", "Hiking"],
          ["Hiking"],
          ["Unemployed"],
          ["1999-09-20 00:00:00"],
          ["Female"],
          ["Bachelor's degree"],
          ["Less then 20.000 EUR"],
          ["Single"],
          ["Netherlands", "Netherlands"],
          ["1399"],
          ["Prolific Participant"],
          ["English", "Dutch", "German"],
          ["Operations", "Unemployed"],
          ["None"],
          ["None"],
          ["Health & Beauty", "Clothing & Shoes", "Books", "None"],
          ["Whatsapp", "Youtube", "Instagram", "None"],
          [
            "TV (Local/Cable News Broadcast)",
            "TV (Late Night Comedy, Other)",
            "Radio (AM/FM, Internet, Satellite)",
            "Print (Newspapers & Periodicals)",
            "None",
          ],
        ],
      ],
    },
  ],
};

I am transforming it to the following shape with a function I have:

const sample = [
  {
    name: "123ilSE",
    longitude: 5.1193,
    latitude: 52.3246,
    agreeableness: 0.147083333333333,
    openness: 0.211041666666667,
    neuroticism: 0.168833333333333,
    extraversion: 0.150291666666666,
    conscientiousness: 0.187041666666666,
    angry: 0.0441711768507957,
    fear: 0.020498564466834,
    joy: 0.875858068466186,
    sadness: 0.0477884039282798,
    love: 0.00839435961097478,
    country: "Netherlands",
    question1: ["Right"],
    question2: ["Student Loan", "None"],
    question3: ["Not at all, i’d rather rent all assets."],
    question4: ["Another benefit"],
    question5: ["Every two weeks", "Yearly a few times"],
    question6: [
      "None",
      "1 to 2 hours",
      "1 to 2 hours",
      "3 hours or more",
      "Less then 1 hour",
    ],
    question7: ["Two to Three Times a Week"],
    question8: [
      "1 to 2 hours",
      "1 to 2 hours",
      "3 hours or more",
      "Less then 1 hour",
    ],
    question9: [
      "1 to 2 hours",
      "1 to 2 hours",
      "3 hours or more",
      "Less then 1 hour",
    ],
    question10: [
      "None",
      "1 to 2 hours",
      "1 to 2 hours",
      "3 hours or more",
      "Less then 1 hour",
    ],
    question11: ["Every two weeks", "Yearly a few times"],
    question12: ["Two to Three Times a Week"],
    question13: ["Every Year"],
    question14: ["Banking & Financial Services", "Unemployed"],
    question15: ["I don't have a car"],
    question16: ["Netherlands", "Netherlands"],
    question17: ["3 - 4 persons"],
    question18: ["Maybe, it depends if nothing betters comes up"],
    question19: ["Desktop"],
    question20: [],
    question21: ["I don't drive or have a car"],
    question22: [
      "E, I can be found on social media platforms and maintain my profile but do little else.",
    ],
    question23: ["None", "Healthcare Insurance"],
    question24: ["None", "Hockey", "Hiking"],
    question25: ["Hiking"],
    question26: ["Unemployed"],
    question27: ["1999-09-20 00:00:00"],
    question28: ["Female"],
    question29: ["Bachelor's degree"],
    question30: ["Less then 20.000 EUR"],
    question31: ["Single"],
    question32: ["Netherlands", "Netherlands"],
    question33: ["1399"],
    question34: ["Prolific Participant"],
    question35: ["English", "Dutch", "German"],
    question36: ["Operations", "Unemployed"],
    question37: ["None"],
    question38: ["None"],
    question39: ["Health & Beauty", "Clothing & Shoes", "Books", "None"],
    question40: ["Whatsapp", "Youtube", "Instagram", "None"],
    question41: [
      "TV (Local/Cable News Broadcast)",
      "TV (Late Night Comedy, Other)",
      "Radio (AM/FM, Internet, Satellite)",
      "Print (Newspapers & Periodicals)",
      "None",
    ],
  },
];

This is the function computeData which I used to map over the array and then apply reduce() twice in order to get the object in the format I need. filters is an array which contains the keys of the final object. I am aware this is not the most efficient manner to do so, therefore I need help with improving this and not using reduce() twice in function computeData.

const filters = [
  "name",
  "longitude",
  "latitude",
  "agreeableness",
  "openness",
  "neuroticism",
  "extraversion",
  "conscientiousness",
  "angry",
  "fear",
  "joy",
  "sadness",
  "love",
  "country",
  "question1",
  "question2",
  "question3",
  "question4",
  "question5",
  "question6",
  "question7",
  "question8",
  "question9",
  "question10",
  "question11",
  "question12",
  "question13",
  "question14",
  "question15",
  "question16",
  "question17",
  "question18",
  "question19",
  "question20",
  "question21",
  "question22",
  "question23",
  "question24",
  "question25",
  "question26",
  "question27",
  "question28",
  "question29",
  "question30",
  "question31",
  "question32",
  "question33",
  "question34",
  "question35",
  "question36",
  "question37",
  "question38",
  "question39",
  "question40",
  "question41",
];

const computeData = ({ records } = {}) => {
  return (
    records &&
    records.map(({ _fields }) => {
      const screenName = _fields[0];
      const country = _fields[2][0];
      const userPersonality = filters.reduce((acc, curr, idx) => {
        if (idx === 0) {
          acc[curr] = screenName;
        } else if (idx >= 1 && idx <= 12) {
          acc[curr] = parseFloat(_fields[1][idx - 1]);
        } else if (idx === 13) {
          acc[curr] = country;
        }
        return acc;
      }, {});
      const questions = _fields[3];
      const finalResults = filters.reduce((acc, curr, idx) => {
        if (idx > 13) {
          questions[idx - 14]
            ? (acc[curr] = questions[idx - 14])
            : (acc[curr] = []);
        }
        return acc;
      }, userPersonality);
      return finalResults;
    })
  );
};

Advertisement

Answer

Given the array of responses, you can map them to an array of entries for the new object by using the index parameter in .map and concatenating with 'question'. Then pass the result to Object.fromEntries.

The other properties like "Longitude:5.1193" can be split on : and also be passed to Object.fromEntries.

const result={records:[{keys:["names","value","country","questions"],length:4,_fields:["123ilSE",["Longitude:5.1193","Latitude:52.3246","Agreeableness:0.147083333333333","Openness:0.211041666666667","Neuroticism:0.168833333333333","Extraversion:0.150291666666666","Conscientiousness:0.187041666666666","Angry:0.0441711768507957","Fear:0.020498564466834","Joy:0.875858068466186","Sadness:0.0477884039282798","Love:0.00839435961097478"],["Netherlands","Netherlands"],[["Right"],["Student Loan","None"],["Not at all, i’d rather rent all assets."],["Another benefit"],["Every two weeks","Yearly a few times"],["None","1 to 2 hours","1 to 2 hours","3 hours or more","Less then 1 hour"],["Two to Three Times a Week"],["1 to 2 hours","1 to 2 hours","3 hours or more","Less then 1 hour"],["1 to 2 hours","1 to 2 hours","3 hours or more","Less then 1 hour"],["None","1 to 2 hours","1 to 2 hours","3 hours or more","Less then 1 hour"],["Every two weeks","Yearly a few times"],["Two to Three Times a Week"],["Every Year"],["Banking & Financial Services","Unemployed"],["I don't have a car"],["Netherlands","Netherlands"],["3 - 4 persons"],["Maybe, it depends if nothing betters comes up"],["Desktop"],[],["I don't drive or have a car"],["E, I can be found on social media platforms and maintain my profile but do little else."],["None","Healthcare Insurance"],["None","Hockey","Hiking"],["Hiking"],["Unemployed"],["1999-09-20 00:00:00"],["Female"],["Bachelor's degree"],["Less then 20.000 EUR"],["Single"],["Netherlands","Netherlands"],["1399"],["Prolific Participant"],["English","Dutch","German"],["Operations","Unemployed"],["None"],["None"],["Health & Beauty","Clothing & Shoes","Books","None"],["Whatsapp","Youtube","Instagram","None"],["TV (Local/Cable News Broadcast)","TV (Late Night Comedy, Other)","Radio (AM/FM, Internet, Satellite)","Print (Newspapers & Periodicals)","None"]]]}]};

const [name, otherProps, [country], responsesArr] = result.records[0]._fields;
const output = {
  name,
  ...Object.fromEntries(otherProps.map(str => {
    const [key, val] = str.split(':');
    return [key, Number(val)];
  })),
  country,
  ...Object.fromEntries(responsesArr.map(
    (responses, i) => ['question' + (i + 1), responses]
  ))
};
console.log(output);
Advertisement