7

I get a JSON response of shoe sizes from an API endpoint that looks like this:

data: [{
    0: {
        system: "US",
        sizes: {
            7: {B: 3, C: 6, D: 1, E: 1}
            7.5: {A: 6, B: 7, C: 14, D: 11, E: 2}
            8: {2E: 1, A: 5, B: 32, C: 38, D: 23, …}
            8.5: {2E: 2, A: 9, B: 56, C: 79, D: 61, …}
            9: {2A: 5, 2E: 4, A: 17, B: 92, C: 143, …}
            9.5: {2A: 3, 2E: 3, A: 26, B: 132, C: 194, …}
            10: {2A: 5, 2E: 3, 3A: 1, A: 53, B: 159, …}
        }
    }
}]

The data shows e.g that US size 7 has four different kinds of shapes (B, C, D, E) where 3 people have foots of shape B. In total, 11 people has size 7. The list can contain sizes in US, EU or different systems, and key of shapes can be A-Z or basically anything else.

I want to loop over sizes and create a diagram of how many people that has a certain size, and how many has a certain shape of that size.

What would be the best way to loop over an object like this to get the value of every shape? I would expect it to be an array of sizes.

ES6 or ES7 is fine but I would prefer to do it without jQuery.

EDIT: Let me be more clear. First of all I have considered improving data structure but unfortunately that's not an option.

I have tried Object.keys(sizes) which returns an array of the keys. Sure that's one step forward. But I would like to call a function that returns an object with the keys and its values. In my mind, that return value should be something like this:

sizes: [
    {
        size: 7,
        total: 11
        shapes: [
            {name: 'B', value: 3},
            {name: 'C', value: 6},
            {name: 'D', value: 1},
            {name: 'E', value: 1}
        ]
    },{...},{...}
]

Does that makes sense? Of course, length is not absolutely necessary to include in the object.

4
  • Well, you already have the data for how many people have a certain shape in size x, because that's the data you've provided. Commented Nov 15, 2017 at 16:03
  • How would you do this with jQuery? Commented Nov 15, 2017 at 16:07
  • FWIW, the data you've added to the question has errors. Commented Nov 15, 2017 at 16:08
  • An array of objects with nested objects... Consider improving your data structure. Commented Nov 15, 2017 at 16:08

3 Answers 3

7

You can extract all of the keys of an object into an array and simply iterate over that array.

var obj = {
  'key1': 'val1',
  'key2': 'val2'
}
var keys = Object.keys(obj); // ['key1', 'key2']
keys.forEach( function(key) {
  var values = obj[key]
  console.log(values)
  // do stuff with "values"
})


Reference -

Sign up to request clarification or add additional context in comments.

Comments

3

You can use array#map, Object.keys() and array#reduce.

const data = [{system:'US',sizes:{7:{B:3,C:6,D:1,E:1,}, 7.5: { A: 6, B: 7, C: 14, D: 11, E: 2, }, 8: { '2E': 1, A: 5, B: 32, C: 38, D: 23, }, 8.5: { '2E': 2, A: 9, B: 56, C: 79, D: 61, }, 9: { '2A': 5, '2E': 4, A: 17, B: 92, C: 143, }, 9.5: { '2A': 3, '2E': 3, A: 26, B: 132, C: 194, }, 10: { '2A': 5, '2E': 3, '3A': 1, A: 53, B: 159, }, }, }, ];

var result = data.map((obj) => {
  return Object.keys(obj.sizes).reduce((arr,k) => {
    let res = Object.keys(obj.sizes[k]).reduce((r, k1) => {
      r['size'] = k;
      r.shapes.push({name: k1, value: obj.sizes[k][k1]});
      r.total += obj.sizes[k][k1];
      return r;
    },{shapes:[],total:0});
    arr.push(res);
    return arr;
  },[]);
})

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

2 Comments

Thank you Hassan, that does the work! Since data is an array with only one item I removed the data.map() and instead assigned the first Object.keys(data[0].sizes).reduce(...) to the result variable. Now I know reduce is the way to go when combining to a single value.
I thought, you might have more values in data, that's why I used it. Yes, array#reduce are wonderful utility to accumulate result. Happy Coding!
1

Use Object.keys() and .reduce() to sum the values of the keys.

NOTE: I had to clean your data, and remove a level to simplify the example. You'll need to adapt it to your real data.

const data = [
	{
		system: 'US',
		sizes: {
			7: {
				B: 3,
				C: 6,
				D: 1,
				E: 1,
			},
			7.5: {
				A: 6,
				B: 7,
				C: 14,
				D: 11,
				E: 2,
			},
			8: {
				'2E': 1,
				A: 5,
				B: 32,
				C: 38,
				D: 23,
			},
			8.5: {
				'2E': 2,
				A: 9,
				B: 56,
				C: 79,
				D: 61,
			},
			9: {
				'2A': 5,
				'2E': 4,
				A: 17,
				B: 92,
				C: 143,
			},
			9.5: {
				'2A': 3,
				'2E': 3,
				A: 26,
				B: 132,
				C: 194,
			},
			10: {
				'2A': 5,
				'2E': 3,
				'3A': 1,
				A: 53,
				B: 159,
			},
		},
	},
];

const { // We use destructuration to make a copy
	sizes = {} // We assign a default value in case sizes is undefined
} = data[0];
const sumOfSizes = {}; // Future object we will fill
Object.keys(sizes).forEach((sizeIndex) => { // We get the keys of the object, and loop over it.
	const size = sizes[sizeIndex]; // For clarity, I assigned the needed value to a var.
	const sumOfShapes = Object.keys(size).reduce((prevSum, shapeIndex) => { // We get the sub-keys of the object and sum the values of them.
		const shapeValue = size[shapeIndex];
		return prevSum + shapeValue;
	}, 0);
	sumOfSizes[sizeIndex] = sumOfShapes; // We assign the sum of shapes to the current shoe size.
});
console.log(sumOfSizes);

Comments

Your Answer

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.