Search code examples
javascriptcomparejavascript-objects

compare nested arrays of objects


Could you help me plese? I need to compare and calculate the percentage of the difference between the values ​​and return an array. I need to compare arrays, get to objects with name and value, and count the percentage. Suppose for the first item in array {name: 'Name 1', value: 1945}, go into the second item to find there {name: 'Name 1', value: 699}. The percentage for 1945 will be 100, for 699 - 36. I'm confused about nesting((

//input data
const data = [
  {
    _id: "0090908",
    groups: [
      {
        _id: "24424",
        name: "Group 1",
        group_type: "group_1",
        items: [
          { name: "Name 1", value: 1945 },
          { name: "Name 2", value: 0 },
          { name: "Name 3", value: 39 },
        ],
      },
      {
        _id: "23030",
        name: "Group 2",
        group_type: "group_2",
        items: [
          { name: "Name 4", value: 67 },
          { name: "Name 5", value: 123 },
          { name: "Name 6", value: 13 },
        ],
      },
    ]
  },
  {
    _id: "00390395",
    groups: [
      {
        _id: "837583",
        name: "Group 1",
        group_type: "group_1",
        items: [
          { name: "Name 1", value: 699 },
          { name: "Name 2", value: 55},
          { name: "Name 3", value: 39 },
        ],
      },
      {
        _id: "8989305",
        name: "Group 2",
        group_type: "group_2",
        items: [
          { name: "Name 4", value: 998 },
          { name: "Name 5", value: 12 },
          { name: "Name 6", value: 485 },
        ],
      },
    ]
  }
];

//result data
const result = [
  {
    _id: "0090908",
    groups: [
      {
        _id: "24424",
        name: "Group 1",
        group_type: "group_1",
        items: [
          { name: "Name 1", value: 1945, percent: 100, best: true },
          { name: "Name 2", value: 0, percent: 0, best: false },
          { name: "Name 3", value: 39, percent: 100, best: true },
        ],
      },
      {
        _id: "23030",
        name: "Group 2",
        group_type: "group_2",
        items: [
          { name: "Name 4", value: 67, percent: 6, best: false },
          { name: "Name 5", value: 123, percent: 100, best: true },
          { name: "Name 6", value: 13, percent: 3, best: true },
        ],
      },
    ]
  },
  {
    _id: "00390395",
    groups: [
      {
        _id: "837583",
        name: "Group 1",
        group_type: "group_1",
        items: [
          { name: "Name 1", value: 699, percent: 36, best: false },
          { name: "Name 2", value: 55, percent: 100, best: true},
          { name: "Name 3", value: 39, percent: 100, best: true },
        ],
      },
      {
        _id: "8989305",
        name: "Group 2",
        group_type: "group_2",
        items: [
          { name: "Name 4", value: 998, percent: 100, best: true },
          { name: "Name 5", value: 12, percent: 9, best: false },
          { name: "Name 6", value: 485, percent: 100, best: true },
        ],
      },
    ]
  }
];


Solution

  • First you need to run through all elements, finding the largest values of each name. Then you run again, placing the percentages.

    var best = {}; // Our database of higher values
    
    function checkLargest(data) {
      if (!data) return;
      // If is iterable perform the function on each element
      if (Symbol.iterator in Object(data)) for (var el of data) checkLargest(el);
      if (data.name && data.value !== undefined)
        if (!best[data.name] || best[data.name] < data.value)
          best[data.name] = data.value;
      checkLargest(data.groups); // If doesn't exist will return
      checkLargest(data.items);
    }
    
    function placePercentages(data) {
      if (!data) return;
      if (Symbol.iterator in Object(data)) for (var el of data) placePercentages(el);
      if (data.name && data.value !== undefined) {
        var higher = best[data.name];
        data.percent = Math.round(data.value / higher * 100);
        data.best = (higher == data.value);
      }
      placePercentages(data.groups);
      placePercentages(data.items);
    }
    
    const d = [
      {
        _id: "0090908",
        groups: [
          {
            _id: "24424",
            name: "Group 1",
            group_type: "group_1",
            items: [
              { name: "Name 1", value: 1945 },
              { name: "Name 2", value: 0 },
              { name: "Name 3", value: 39 },
            ],
          },
          {
            _id: "23030",
            name: "Group 2",
            group_type: "group_2",
            items: [
              { name: "Name 4", value: 67 },
              { name: "Name 5", value: 123 },
              { name: "Name 6", value: 13 },
            ],
          },
        ]
      },
      {
        _id: "00390395",
        groups: [
          {
            _id: "837583",
            name: "Group 1",
            group_type: "group_1",
            items: [
              { name: "Name 1", value: 699 },
              { name: "Name 2", value: 55},
              { name: "Name 3", value: 39 },
            ],
          },
          {
            _id: "8989305",
            name: "Group 2",
            group_type: "group_2",
            items: [
              { name: "Name 4", value: 998 },
              { name: "Name 5", value: 12 },
              { name: "Name 6", value: 485 },
            ],
          },
        ]
      }
    ];
    
    checkLargest(d);
    placePercentages(d);
    console.log(d);