javascript - How do i find and count unique values in nested JSON objects? - Stack Overflow

admin2025-04-22  0

i have the following JavaScript

{
  "business": [
{
  "order_contents": [
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 85,
      "name": "product 3",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 84,
      "name": "product 2",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 84,
      "name": "product 2",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    }
   ]
  }
 ]
}

What i am trying to acplish is when the order es through a function scans the JSON and creates an array with each unique product name and adds 1 to the quantity each time.

i have tried using a for loop but it loops it the amount of times but doesn't find the name and value in the nested object of each one, it es back as name = 0 and the value being the individual nested object inside the main object.

i have the following JavaScript

{
  "business": [
{
  "order_contents": [
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 85,
      "name": "product 3",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 84,
      "name": "product 2",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 83,
      "name": "product 1",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    },
    {
      "id": 84,
      "name": "product 2",
      "price": "1.99",
      "quantity": 1,
      "total": "1.99",
      "ingredients": [],
      "extras": []
    }
   ]
  }
 ]
}

What i am trying to acplish is when the order es through a function scans the JSON and creates an array with each unique product name and adds 1 to the quantity each time.

i have tried using a for loop but it loops it the amount of times but doesn't find the name and value in the nested object of each one, it es back as name = 0 and the value being the individual nested object inside the main object.

Share Improve this question edited Dec 26, 2014 at 12:24 user663031 asked Dec 26, 2014 at 0:04 Ryan KRyan K 3464 silver badges15 bronze badges 5
  • 1 What does your function look like which does the looping and adding to the quantity? – Chris Commented Dec 26, 2014 at 0:29
  • JSON is a string. It can be converted to a javascript Object using JSON.parse(string), which can then be treated like any other Object. – RobG Commented Dec 26, 2014 at 0:40
  • What does the output array look like that contains names and counts? – RobG Commented Dec 26, 2014 at 0:43
  • I'm assuming you want output of something like [{"product 2":15}]? – whitfin Commented Dec 26, 2014 at 0:52
  • Okay.. so are you're trying to reduce the array items based on their name into separate arrays? – Edward J Beckett Commented Dec 26, 2014 at 1:41
Add a ment  | 

3 Answers 3

Reset to default 4

A function like the beneath would work. Basically you pass the array as parameter and return an object that 1) gets a new property if the property does not exist yet (eg. the product id), and 2) adds to the count of items when the property does exist. The function below generates an output like: {'product 1': 10, 'product 2': 1, 'product 3': 2}

function getItems(input) {
  var arr = input, obj = {};
  for (var i = 0; i < arr.length; i++) {
    if (!obj[arr[i].name]) {
      obj[arr[i].name] = 1;
    } else if (obj[arr[i].name]) {
      obj[arr[i].name] += 1;
    }
  }
  return obj;
}
// example use
console.log(getItems(order_contents)); // outputs entire object
console.log(getItems(order_contents)['product 1']); // outputs 10

Seeing that you need unique names for each product... you can push the objects into a grouped array of objects then reduce the objects into single unique objects.

var data={"business":[{"order_contents":[{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":85,"name":"product 3","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":84,"name":"product 2","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":83,"name":"product 1","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]},{"id":84,"name":"product 2","price":"1.99","quantity":1,"total":"1.99","ingredients":[],"extras":[]}]}]};

function buildData() {
	var items = data.business[0].order_contents, elems = [], groups = [];
	for( var i = 0; i < items.length; i++ ) {
		Array.prototype.push.call( elems, items[i] );
	}
	groups.push( groupBy( elems, function( item ) {
		return item;
	} ) );
	groupBy( groups, function( array ) {
		for( var i = 0; i < array.length; i++ ) {
			var obj = array[i].slice();
			Object.keys( obj ).map( function( p ) {
				var length = obj.length;
				if( obj[p].hasOwnProperty( "quantity" ) ) {
					obj[p].quantity = length;
				}
				groups[i] = obj[p];
			} );
		}
	} );
	function groupBy( array, f ) {
		var groups = {};
		array.forEach( function( o ) {
			var group = JSON.stringify( f( o ) );
			groups[group] = groups[group] || [];
			groups[group].push( o );
		} );
		return Object.keys( groups ).map( function( group ) {
			return groups[group];
		} );
	}

	return groups;
}

(function() {
	var old = console.log;
	var logger = document.getElementById( 'log' );
	console.log = function( message ) {
		if( typeof message == 'object' ) {
			logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify( message, undefined, 2 ) : message) + '<br />';
		} else {
			logger.innerHTML += message + '<br />';
		}
	}
})();

console.log( buildData() );
<pre id="log">
</pre>

Not a big fan of reinventing the wheel, so here is how you could use object-scan to answer your question

// const objectScan = require('object-scan');

const counts = (haystack) => objectScan(['business[*].order_contents[*].name'], {
  filterFn: ({ value, context }) => {
    context[value] = (context[value] || 0) + 1;
  }
})(haystack, {});

const data = { business: [{ order_contents: [{ id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 85, name: 'product 3', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 84, name: 'product 2', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 83, name: 'product 1', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }, { id: 84, name: 'product 2', price: '1.99', quantity: 1, total: '1.99', ingredients: [], extras: [] }] }]};

console.log(counts(data));
// => { 'product 2': 2, 'product 1': 10, 'product 3': 1 }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745289828a294616.html

最新回复(0)