Эврити c - это просто подсчет количества символов {
, }
, [
и ]
. Конечно, это всего лишь heuristi c; при этом методе объект json, например { value: "{[}{}][{{}{}]{}{}{}[}}{}{" }
, будет считаться чрезмерно сложным, даже если его структура очень проста.
let guessJsonComplexity = (json, chars=new Set([ '{', '}', '[', ']' ])) => {
let count = 0;
for (let char in json) if (chars.has(char)) count++;
return count / (json.length || 1);
};
Вы должны go с этим ответом, если скорость очень важно.
Вам почти наверняка потребуется проанализировать json, если вы хотите более лаконичный ответ!
Мы могли бы также рассмотреть другой подход. Подумайте о том, чтобы присвоить «оценку сложности» каждому возможному явлению, которое может произойти в json. Например:
- Включена строка
s
; оценка сложности: Math.log(s.length)
- Включено число
n
; оценка сложности: Math.log(n)
- Включено логическое значение; оценка сложности: 1
- Массив включен; оценка сложности: средняя сложность элементов + 1
- Объект включен; оценка сложности: средняя сложность значений плюс средняя сложность ключей + 1
Мы могли бы даже выделить отдельные отношения, такие как «объект включен в массив» или «массив включен в array ", et c, если мы хотим рассматривать некоторые из них как более" сложные ", чем другие. Мы могли бы, например, сказать, что отрицательные числа вдвое более «сложны», чем положительные, если мы так думаем.
Мы также можем рассмотреть «коэффициент глубины», который заставляет элементы считать больше, чем глубже они go.
Если мы определим, как оценивать все эти явления, мы можем написать функцию, которая обрабатывает json и применяет такую оценку:
let isType = (val, Cls) => val != null && val.constructor === Cls;
let getComplexity = (json, d=1.05) => {
// Here `d` is our "depth factor"
return d * (() => {
// Take the log of the length of a String
if (isType(json, String)) return Math.log(json.length);
// Take the log of (the absolute value of) any Number
if (isType(json, Number)) return Math.log(Math.abs(json));
// Booleans always have a complexity of 1
if (isType(json, Boolean)) return 1;
// Arrays are 1 + (average complexity of their child elements)
if (isType(json, Array)) {
let avg = json.reduce((o, v) => o + getComplexity(v, d), 0) / (json.length || 1);
return avg + 1;
}
// Objects are 1 + (average complexity of their keys) + (average complexity of their values)
if (isType(json, Object)) {
// `getComplexity` for Arrays will add 1 twice, so subtract 1 to compensate
return getComplexity(Object.keys(json), d) + getComplexity(Object.values(json), d) - 1;
}
throw new Error(`Couldn't get complexity for ${json.constructor.name}`);
})();
};
console.log('Simple:', getComplexity([ 'very', 'simple' ]));
console.log('Object:', getComplexity({
i: 'am',
some: 'json',
data: 'for',
testing: 'purposes'
}));
console.log('Complex:', getComplexity([
[ 111, 222, 333, 444 ],
[ 'abc', 'def', 'ghi', 'jkl' ],
[ [], [], {}, {}, 'abc', true, false ]
]));
console.log('Deep:', getComplexity([[[[[[ 'hi' ]]]]]]));
Если вы хотите узнать более подробную информацию о дочерних объектах большого json объекта, вы можете просто позвонить getComplexity
и этим дочерним объектам.