0
\$\begingroup\$

The code below reduces an array into "named" objects (not sure if that's the correct terminology!)

It works, but I'm sure the code could be improved. There is some repetition going on in the reduce.

It checks if a key exists (if (accumulator[name])). If not then initialize the results array, if it does then push onto the results array.

let response = {
  columns: [
    'n'
  ],
  data: [
    {
      graph: {
        nodes: [
          {
            id: '169',
            labels: [
              'Container'
            ],
            properties: {
              reference: 'REF002',
              name: 'Cupboard',
              id: '003'
            }
          }
        ],
        relationships: []
      }
    },
    {
      graph: {
        nodes: [
          {
            id: '170',
            labels: [
              'Container'
            ],
            properties: {
              reference: 'REF003',
              name: 'Cupboard A',
              id: '03a'
            }
          }
        ],
        relationships: []
      }
    },
    {
      graph: {
        nodes: [
          {
            id: '964',
            labels: [
              'Equipment'
            ],
            properties: {
              reference: 'REF004',
              name: 'Cupboard B',
              id: '03b'
            }
          }
        ],
        relationships: []
      }
    }
  ]
}

const result = response.data.reduce(
  (accumulator, currentValue, currentIndex, array) => {
    const name = currentValue.graph.nodes[0].labels[0];

    if (accumulator[name]) {
      accumulator[name].results.push({
        title: currentValue.graph.nodes[0].properties.name,
        description: currentValue.graph.nodes[0].properties.reference
      });
    } else {
      accumulator[name] = {
        name,
        results: [
          {
            title: currentValue.graph.nodes[0].properties.name,
            description: currentValue.graph.nodes[0].properties.reference
          }
        ]
      };
    }

    return accumulator;
  },
  {}
);

console.clear();
console.log(result);

Output Required

{
  Container: {
    name: 'Container',
    results: [
      {
        title: 'Cupboard',
        description: 'REF002'
      },
      {
        title: 'Cupboard A',
        description: 'REF003'
      }
    ]
  },
  Foo: {
    name: 'Foo',
    results: [
      {
        title: 'Cupboard B',
        description: 'REF004'
      }
    ]
  }
}
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

As it looks like you are using ES6 syntax, you could also throw in some destructuring assignments, but I guess the main point is that one would need to create the output object only once. One could also extract the accumulation into a descriptive name:

byFirstLabel = (acc, {graph: {nodes: [node]}}) => {
  let label = node.labels[0]
  let { name: title, reference: description } = node.properties
  let entry = { title, description }

  acc[label] ? acc[label].results.push(entry) :
    acc[label] = { name: label, results: [ entry ] }

  return acc
}

response.data.reduce(byFirstLabel, {})
\$\endgroup\$
2
1
\$\begingroup\$

You could try this. Keep the push logic as the only way to add results and separate out the initialisation logic to the || condition before itself

let response = {
  columns: [
    'n'
  ],
  data: [{
      graph: {
        nodes: [{
          id: '169',
          labels: [
            'Container'
          ],
          properties: {
            reference: 'REF002',
            name: 'Cupboard',
            id: '003'
          }
        }],
        relationships: []
      }
    },
    {
      graph: {
        nodes: [{
          id: '170',
          labels: [
            'Container'
          ],
          properties: {
            reference: 'REF003',
            name: 'Cupboard A',
            id: '03a'
          }
        }],
        relationships: []
      }
    },
    {
      graph: {
        nodes: [{
          id: '964',
          labels: [
            'Equipment'
          ],
          properties: {
            reference: 'REF004',
            name: 'Cupboard B',
            id: '03b'
          }
        }],
        relationships: []
      }
    }
  ]
}

const result = response.data.reduce(
  (accumulator, currentValue, currentIndex, array) => {
    // Create a node const to avoid repeating it
    const node = currentValue.graph.nodes[0];
    const name = node.labels[0];
    // Move initialization logic here
    accumulator[name] = accumulator[name] || {
      name,
      results: []
    };

    // There is no need for the previous check anymore
    accumulator[name].results.push({
      title: node.properties.name,
      description: node.properties.reference
    });

    return accumulator;
  }, {}
);

console.clear();
console.log(result);

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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