0

I have two functions that group a list of dicts according to the value of a certain key. Here's how my array looks:

const sections = [
  {
    file_id: '1',
    heading_level: 4,
    readme_file_name: 'Quick.Quick.md',
    section_codes: [
      1,
      3,
    ],
    section_id: '1',
    title: 'Nimble',
  },
  {
    file_id: '1',
    heading_level: 2,
    readme_file_name: 'Quick.Quick.md',
    section_codes: [
      3,
      4,
    ],
    section_id: '2',
    title: 'Swift Version',
  },
  // ...
];

Some times I need to group the sections by it's heading_level key value, and other times I need to group by the first value on section_codes array.

I've created a single function for each grouping, but the code is exactly the same, except for the line where I access the desired key. So I've tried removing duplication, and here's where I've gotten so far:

// Helper func
function getValueForKey(key, section) {
  const originalValue = section[key];

  if (Array.isArray(originalValue)) {
    return originalValue[0];
  }

  return originalValue;
}

export function groupSectionsByKey(key, sections) {
  const groupedSections = {};

  sections.forEach((section) => {
    const groupKey = getValueForKey(key, section);
    const codeArray = groupedSections[groupKey];

    if (codeArray) {
      codeArray.push(section);
    } else {
      groupedSections[groupKey] = [section];
    }
  });

  return groupedSections;
}

This getValueForKey function seems a bit off for me, but I'm not sure if there is a better way to do this. Does anyone have some feedback?

Thanks.

  • Secondly you can pass function to your function to make it more customizable. And first of all use lodash or underscore and change your imperative style to functional. Everything you are looking for was already implemented. – Tomasz Maciejewski Jun 10 at 15:21
  • @TomaszMaciejewski thanks for the reply. Do you mean letting whoever calls getValueForKey pass it's own implementation of getValueForKey as parameter? Also, could give me some concrete examples of how loads and underscore solve this problem, as I am not familiar with them? Thanks. – Hilton Pintor Bezerra Leite Jun 10 at 15:49
0

Solution using lodash, I really recommend to read docs of this valuable library https://lodash.com. In addition to this please read about functional style in JS as it creates much more concise and readable solution in most cases.

const { groupBy } = require('lodash');

const sections = [
    {
      file_id: '1',
      heading_level: 4,
      readme_file_name: 'Quick.Quick.md',
      section_codes: [
        1,
        3,
      ],
      section_id: '1',
      title: 'Nimble',
    },
    {
      file_id: '1',
      heading_level: 2,
      readme_file_name: 'Quick.Quick.md',
      section_codes: [
        3,
        4,
      ],
      section_id: '2',
      title: 'Swift Version',
    },
    // ...
  ];

  const groupSectionsByKey = (sections, key) => groupBy(sections, (section) => Array.isArray(section[key]) ? section[key][0] : section[key]);
  const sectionsGroupedByCode = groupSectionsByKey(sections, "section_codes"); //example execution with section_codes
  console.log(sectionsGroupedByCode );
  • Thanks so much for the example. So it seems like I wasn't very off. From what I understood, if I add a function parameter to my groupSectionsByKey letting the caller specify how the key should be accessed, then I'd have the same behavior as lodash. – Hilton Pintor Bezerra Leite Jun 11 at 17:09
  • The difference is significant - in functional style which is a type of declarative paradigm you only say 'what' not 'how'. You can try as an exercise add some more processing e.g. groupBy section but only if title is X and collect the heading level using both your previous approach and lodash. – Tomasz Maciejewski Jun 12 at 10:28
  • I don't think you need a groupSectionsByKey any more. Just use groupBy(sections, (section) => sections.section_codes[0]); – immibis Jun 14 at 3:02
  • @immibis groupSectionsByKey is generic function which allows to pass the key by which you group by, so that you don't need to repeat the same code with heading_level, title, etc. – Tomasz Maciejewski Jun 14 at 9:31
  • @TomaszMaciejewski Yeah, but groupBy also allows you to pass the key by which you group by. It's the second parameter and it can be any expression, instead of having to be a field name. – immibis Jun 16 at 21:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.