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'
 }
 ]
 }
}
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Oct 20, 2017 at 8:52
\$\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, {})
answered Oct 20, 2017 at 11:53
\$\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);

answered Oct 20, 2017 at 11:41
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.