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\$

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.