Как я могу легко измерить сложность объекта JSON? - PullRequest
5 голосов
/ 06 августа 2020

Если я хочу сравнить диапазон ответов API на предмет сложности ответа (в качестве прокси для того, сколько усилий, вероятно, потребуется для анализа и проверки ответа), есть ли какой-либо существующий инструмент или библиотека, которые могут сделать это довольно эффективно ? или простой фрагмент кода?

В идеале что-то, что распечатывает быстрый отчет, показывающий, насколько глубока и широка вся структура, вместе с любыми другими показателями, которые могут быть полезны.

Ответы [ 2 ]

2 голосов
/ 07 августа 2020

Эврити 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 и этим дочерним объектам.

0 голосов
/ 07 августа 2020

Я использую произвольные значения, но это просто для того, чтобы дать вам начальную точку.

var data1 = { "a": { "b": 2 }, "c": [{}, {}, { "d": [1, 2, 3] }] }
var data2 = { "a": { "b": 2 }, "c": [{"x":"y","z":[0,1,2,3,4,5,6,7,8,9]}, {}, { "d": [1, 2, 3] }] }

function chkComplexity(obj) {
  let complexity = 0;
  let depth = 1;
  (function calc(obj) {
    for (const key of Object.keys(obj)) {
      if (typeof obj[key] !== "object") complexity += depth
      if (Array.isArray(obj)) {
        depth++
        complexity += depth * 2
        for (const item of obj) {
          calc(item)
        }
      }
      if (typeof obj[key] === "object") {
        depth++
        complexity += depth * 3
        calc(obj[key])
      }
    }
  })(obj);
  return complexity;
}
console.log(chkComplexity(data1));
console.log(chkComplexity(data2));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...