fastlanes
fastlanes

Reputation: 333

How to map an array of objects correctly in Javascript

I'm having trouble mapping data to the correct output format I need for a d3 stacked bar visualization due to the complexity of the object I'm working with.

My object currently looks like this


arr = {
    reasons: {
           "No supply": 775,
           "More than 1 wk": 773,
           "1 week or less": 1114
    },
    type: "Napkins"
};

I'd like to get the output as a stack array in following form so that I can visualize using stacked bars (note all values are rounded 2 to 2 decimals for simplicity):

stack = {
   0: {
       reason: "No supply"
       startValue: 0
       value: 0.29
       endValue: 0.29
       type: 'Napkins'
   },
   1: {   
       reason: "More than 1 wk"
       startValue: 0.29
       value: 0.28   
       endValue: 0.58
       type: 'Napkins'
   },
   2: {   
       reason: "1 week or less"
       startValue: 0.58
       value: 0.42   
       endValue: 1.0
       type: 'Napkins'
   }
}

I currently have this code to create the stack array but I'm not able to get it populated correctly so I keep getting errors. I believe the mapping here and how I'm accessing the different entries in the array is my problem.

let total = d3.sum(Object.values(arr[1].reasons));  // compute sum across reason values
let value = 0;
let stack = arr.map((d) => ({
          reason: Object.keys(d[1].reasons),
          value: d.value / total,
          startValue: value / total,
          endValue: (value += d.value) / total,
          type: d.type,
        }));

Upvotes: 0

Views: 110

Answers (3)

Halmon
Halmon

Reputation: 1077

I think the main issue is you're trying to call .map() on an object instead of an array. To loop through the object you could use a for loop.

arr = {
    reasons: {
           "No supply": 775,
           "More than 1 wk": 773,
           "1 week or less": 1114
         },
    type: "Napkins"
};
const value = 0
const total = 775+773+1114
let stack = [];
for (let d in arr.reasons) {
 let foo = {
   reason: d,
   value: arr.reasons[d] / total,
   startValue: value / total,
   endValue: (value += arr.reasons[d]) / total,
   type: arr.type,
 }
 stack.push(foo)
}
console.log(stack)

Upvotes: 2

Mahmud
Mahmud

Reputation: 41

    const reasons = Object.entries(arr.reasons);
    let value = 0;
    reasons.map(([key, value], index) => {
      return (
       index: {
          reason: key,
          value: value / total,
          startValue: value / total,
          endValue: (value += value) / total,
          type: arr.type
        }
       )
    });

Upvotes: 1

Derek Wang
Derek Wang

Reputation: 10204

  • To get the total sum, you can use Array.reduce.
  • Using Object.entries, you can get the [key, value] pairs of the object arr.reason.
  • And using Number.toFixed, you can format a number using fixed-point notation.

const arr = {
  reasons: {
    "No supply": 775,
    "More than 1 wk": 773,
    "1 week or less": 1114
  },
  type: "Napkins"
};

const total = Object.values(arr.reasons).reduce((acc, cur) => acc + cur, 0);
let value = 0;
const stack = Object.entries(arr.reasons).map(([key, itemVal]) => ({
  reason: key,
  value: (itemVal / total).toFixed(2),
  startValue: (value / total).toFixed(2),
  endValue: ((value += itemVal) / total).toFixed(2),
  type: arr.type
}));
console.log(stack);

Upvotes: 1

Related Questions