How i can count all objects that have specific key but if object can be nested and I do not know max depth of object because everytime is differente?
for exmaple once can be like this:
{
"coins_series": [
{
"series": 1,
"coins": [
{
"_id": "65c8c78845d911984d98f6be",
"currency": "EUR",
"reverse_id": "SVN200701001REG",
"obverse_id": [
"EUR199901001FRO"
],
"country": "SVN",
"commemorative": false,
"series": 1,
"min_year": 2007,
"denomination": 0.01,
"diameter": 16.25,
"thickness": 1.67,
"weight": 2.3
},
{
"_id": "65c8c78845d911984d98f6bf",
"currency": "EUR",
"reverse_id": "SVN200701002REG",
"obverse_id": [
"EUR199901002FRO"
],
"country": "SVN",
"commemorative": false,
"series": 1,
"min_year": 2007,
"denomination": 0.02,
"diameter": 18.75,
"thickness": 1.67,
"weight": 3.06
},
{
"_id": "65c8c78845d911984d98f6c0",
"currency": "EUR",
"reverse_id": "SVN200701005REG",
"obverse_id": [
"EUR199901005FRO"
],
"country": "SVN",
"commemorative": false,
"series": 1,
"min_year": 2007,
"denomination": 0.05,
"diameter": 21.25,
"thickness": 1.67,
"weight": 3.92
},
{
"_id": "65c8c78845d911984d98f6c1",
"currency": "EUR",
"reverse_id": "SVN200701010REG",
"obverse_id": [
"EUR200702010FRO"
],
"country": "SVN",
"commemorative": false,
"series": 1,
"min_year": 2007,
"denomination": 0.1,
"diameter": 19.75,
"thickness": 1.93,
"weight": 4.1
},
{
"_id": "65c8c78845d911984d98f6c2",
"currency": "EUR",
"reverse_id": "SVN200701020REG",
"obverse_id": [
"EUR200702020FRO"
],
"country": "SVN",
"commemorative": false,
"series": 1,
"min_year": 2007,
"denomination": 0.2,
"diameter": 22.25,
"thickness": 2.14,
"weight": 5.74
},
{
"_id": "65c8c78845d911984d98f6c3",
"currency": "EUR",
"reverse_id": "SVN200701050REG",
"obverse_id": [
"EUR200702050FRO"
],
"country": "SVN",
"commemorative": false,
"series": 1,
"min_year": 2007,
"denomination": 0.5,
"diameter": 24.25,
"thickness": 2.38,
"weight": 7.8
},
{
"_id": "65c8c78845d911984d98f6c4",
"currency": "EUR",
"reverse_id": "SVN200701100REG",
"obverse_id": [
"EUR200702100FRO"
],
"country": "SVN",
"commemorative": false,
"series": 1,
"min_year": 2007,
"denomination": 1,
"diameter": 23.25,
"thickness": 2.33,
"weight": 7.5
},
{
"_id": "65c8c78845d911984d98f6c5",
"currency": "EUR",
"reverse_id": "SVN200701200REG",
"obverse_id": [
"EUR200702200FRO"
],
"country": "SVN",
"commemorative": false,
"series": 1,
"min_year": 2007,
"denomination": 2,
"diameter": 25.75,
"thickness": 2.2,
"weight": 8.5
}
]
}
],
"country": "SVN"
}
and other time can be like this:
{
"series": 2,
"coins": [
{
"_id": "65c8c78845d911984d98f724",
"currency": "EUR",
"reverse_id": "VAT200502001REG",
"obverse_id": [
"EUR199901001FRO"
],
"country": "VAT",
"commemorative": false,
"series": 2,
"min_year": 2005,
"max_year": 2005,
"denomination": 0.01,
"diameter": 16.25,
"thickness": 1.67,
"weight": 2.3
},
{
"_id": "65c8c78845d911984d98f725",
"currency": "EUR",
"reverse_id": "VAT200502002REG",
"obverse_id": [
"EUR199901002FRO"
],
"country": "VAT",
"commemorative": false,
"series": 2,
"min_year": 2005,
"max_year": 2005,
"denomination": 0.02,
"diameter": 18.75,
"thickness": 1.67,
"weight": 3.06
},
{
"_id": "65c8c78845d911984d98f726",
"currency": "EUR",
"reverse_id": "VAT200502005REG",
"obverse_id": [
"EUR199901005FRO"
],
"country": "VAT",
"commemorative": false,
"series": 2,
"min_year": 2005,
"max_year": 2005,
"denomination": 0.05,
"diameter": 21.25,
"thickness": 1.67,
"weight": 3.92
},
{
"_id": "65c8c78845d911984d98f727",
"currency": "EUR",
"reverse_id": "VAT200502010REG",
"obverse_id": [
"EUR199901010FRO"
],
"country": "VAT",
"commemorative": false,
"series": 2,
"min_year": 2005,
"max_year": 2005,
"denomination": 0.1,
"diameter": 19.75,
"thickness": 1.93,
"weight": 4.1
},
{
"_id": "65c8c78845d911984d98f728",
"currency": "EUR",
"reverse_id": "VAT200502020REG",
"obverse_id": [
"EUR199901020FRO"
],
"country": "VAT",
"commemorative": false,
"series": 2,
"min_year": 2005,
"max_year": 2005,
"denomination": 0.2,
"diameter": 22.25,
"thickness": 2.14,
"weight": 5.74
},
{
"_id": "65c8c78845d911984d98f729",
"currency": "EUR",
"reverse_id": "VAT200502050REG",
"obverse_id": [
"EUR199901050FRO"
],
"country": "VAT",
"commemorative": false,
"series": 2,
"min_year": 2005,
"max_year": 2005,
"denomination": 0.5,
"diameter": 24.25,
"thickness": 2.38,
"weight": 7.8
},
{
"_id": "65c8c78845d911984d98f72a",
"currency": "EUR",
"reverse_id": "VAT200502100REG",
"obverse_id": [
"EUR199901100FRO"
],
"country": "VAT",
"commemorative": false,
"series": 2,
"min_year": 2005,
"max_year": 2005,
"denomination": 1,
"diameter": 23.25,
"thickness": 2.33,
"weight": 7.5
},
{
"_id": "65c8c78845d911984d98f72b",
"currency": "EUR",
"reverse_id": "VAT200502200REG",
"obverse_id": [
"EUR199901200FRO"
],
"country": "VAT",
"commemorative": false,
"series": 2,
"min_year": 2005,
"max_year": 2005,
"denomination": 2,
"diameter": 25.75,
"thickness": 2.2,
"weight": 8.5
}
]
}
some other time can be different format. I need to count all objects with commemorative key each time without specific data structure.
You can recursively iterate arrays and objects values and check that the objects contain your key:
const countKey = (obj, key) => {
let count = 0;
if(Array.isArray(obj)){
for(const item of obj){
count += countKey(item, key);
}
} else if (obj && typeof obj === 'object'){
for(const k in obj){
if(k === key) count++;
count += countKey(obj[k], key);
}
}
return count;
};
// Example
const data = {"coins_series": [{"series": 1,"coins": [{"_id": "65c8c78845d911984d98f6be","currency": "EUR","reverse_id": "SVN200701001REG","obverse_id": ["EUR199901001FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.01,"diameter": 16.25,"thickness": 1.67,"weight": 2.3},{"_id": "65c8c78845d911984d98f6bf","currency": "EUR","reverse_id": "SVN200701002REG","obverse_id": ["EUR199901002FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.02,"diameter": 18.75,"thickness": 1.67,"weight": 3.06},{"_id": "65c8c78845d911984d98f6c0","currency": "EUR","reverse_id": "SVN200701005REG","obverse_id": ["EUR199901005FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.05,"diameter": 21.25,"thickness": 1.67,"weight": 3.92},{"_id": "65c8c78845d911984d98f6c1","currency": "EUR","reverse_id": "SVN200701010REG","obverse_id": ["EUR200702010FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.1,"diameter": 19.75,"thickness": 1.93,"weight": 4.1},{"_id": "65c8c78845d911984d98f6c2","currency": "EUR","reverse_id": "SVN200701020REG","obverse_id": ["EUR200702020FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.2,"diameter": 22.25,"thickness": 2.14,"weight": 5.74},{"_id": "65c8c78845d911984d98f6c3","currency": "EUR","reverse_id": "SVN200701050REG","obverse_id": ["EUR200702050FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.5,"diameter": 24.25,"thickness": 2.38,"weight": 7.8},{"_id": "65c8c78845d911984d98f6c4","currency": "EUR","reverse_id": "SVN200701100REG","obverse_id": ["EUR200702100FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 1,"diameter": 23.25,"thickness": 2.33,"weight": 7.5},{"_id": "65c8c78845d911984d98f6c5","currency": "EUR","reverse_id": "SVN200701200REG","obverse_id": ["EUR200702200FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 2,"diameter": 25.75,"thickness": 2.2,"weight": 8.5}]}],"country": "SVN"};
const count = countKey(data, "commemorative");
console.log(count); // 8
And benchmarking:
` Chrome/121
------------------------------------------------------------------------------------
> n=1 | n=10 | n=100 | n=1000
Alexander 1.00x x1m 757 | 1.00x x100k 747 | 1.00x x10k 751 | 1.00x x1k 736
trincot 3.00x x100k 227 | 2.93x x10k 219 | 2.97x x1k 223 | 2.99x x100 220
test30 (JSON) 8.40x x100k 636 | 8.09x x10k 604 | 9.17x x1k 689 | 10.98x x100 808
------------------------------------------------------------------------------------
https://github.com/silentmantra/benchmark `
` Firefox/122
----------------------------------------------------------------------------------
> n=1 | n=10 | n=100 | n=1000
Alexander 1.00x x100k 123 | 1.00x x10k 96 | 1.00x x10k 944 | 1.00x x100 101
trincot 4.07x x100k 501 | 5.47x x10k 525 | 5.74x x1k 542 | 5.24x x100 529
test30 (JSON) 7.39x x100k 909 | 9.11x x10k 875 | 9.43x x1k 890 | 9.13x x100 922
----------------------------------------------------------------------------------
https://github.com/silentmantra/benchmark `
// Example
const $chunk = [{"coins_series": [{"series": 1,"coins": [{"_id": "65c8c78845d911984d98f6be","currency": "EUR","reverse_id": "SVN200701001REG","obverse_id": ["EUR199901001FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.01,"diameter": 16.25,"thickness": 1.67,"weight": 2.3},{"_id": "65c8c78845d911984d98f6bf","currency": "EUR","reverse_id": "SVN200701002REG","obverse_id": ["EUR199901002FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.02,"diameter": 18.75,"thickness": 1.67,"weight": 3.06},{"_id": "65c8c78845d911984d98f6c0","currency": "EUR","reverse_id": "SVN200701005REG","obverse_id": ["EUR199901005FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.05,"diameter": 21.25,"thickness": 1.67,"weight": 3.92},{"_id": "65c8c78845d911984d98f6c1","currency": "EUR","reverse_id": "SVN200701010REG","obverse_id": ["EUR200702010FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.1,"diameter": 19.75,"thickness": 1.93,"weight": 4.1},{"_id": "65c8c78845d911984d98f6c2","currency": "EUR","reverse_id": "SVN200701020REG","obverse_id": ["EUR200702020FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.2,"diameter": 22.25,"thickness": 2.14,"weight": 5.74},{"_id": "65c8c78845d911984d98f6c3","currency": "EUR","reverse_id": "SVN200701050REG","obverse_id": ["EUR200702050FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 0.5,"diameter": 24.25,"thickness": 2.38,"weight": 7.8},{"_id": "65c8c78845d911984d98f6c4","currency": "EUR","reverse_id": "SVN200701100REG","obverse_id": ["EUR200702100FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 1,"diameter": 23.25,"thickness": 2.33,"weight": 7.5},{"_id": "65c8c78845d911984d98f6c5","currency": "EUR","reverse_id": "SVN200701200REG","obverse_id": ["EUR200702200FRO"],"country": "SVN","commemorative": false,"series": 1,"min_year": 2007,"denomination": 2,"diameter": 25.75,"thickness": 2.2,"weight": 8.5}]}],"country": "SVN"}];
const $input = [];
// @benchmark test30 (JSON)
{
let count = 0
JSON.stringify($input, (key, value) => {
if (key === 'commemorative') count++;
return value;
})
count;
}
// @benchmark trincot
const countKey = (obj, key) =>
Object(obj) !== obj ? 0 // A primitive value (base case)
// A boolean indicating a match is coerced to 0 or 1:
: (!Array.isArray(obj) && Object.hasOwn(obj, key)) +
// Recursive calls
Object.values(obj).reduce((sum, obj) => sum + countKey(obj, key), 0);
countKey($input, "commemorative");
// @benchmark Alexander
{
const countKey = (obj, key) => {
let count = 0;
if(Array.isArray(obj)){
for(const item of obj){
count += countKey(item, key);
}
} else if (obj && typeof obj === 'object'){
for(const k in obj){
if(k === key) count++;
count += countKey(obj[k], key);
}
}
return count;
};
countKey($input, "commemorative");
}
/*@end*/eval(atob('e2xldCBlPWRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3Rvcigic2NyaXB0Iik7aWYoIWUubWF0Y2hlcygiW2JlbmNobWFya10iKSl7bGV0IHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7dC5zcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9naC9zaWxlbnRtYW50cmEvYmVuY2htYXJrL2xvYWRlci5qcyIsdC5kZWZlcj0hMCxkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHQpfX0='));