0

I'll cut to the chase.

I want to change the radius value in the following array for a specific ID and dataID:

var data = [{
  ID: 0,
  type: 'circle',
  Name: 'Tom',
  MoreData: [{
    dataID: 123,
    dimData: {
      radius: 25,
      var: 15
    }
  }, {
    dataID: 345,
    dimData: {
      radius: 35,
      var: 65
    }
  }]
}, {
  ID: 1,
  type: 'circle',
  Name: 'Mat',
  MoreData: [{
    dataID: 678,
    dimData: {
      radius: 40,
      var: 30
    }
  }, {
    dataID: 91011,
    dimData: {
      radius: 50,
      var: 50
    }
  }]
}];

My current solution:

    var data = [{
      ID: 0,
      type: 'circle',
      Name: 'Tom',
      MoreData: [{
        dataID: 123,
        dimData: {
          radius: 25,
          var: 15
        }
      }, {
        dataID: 345,
        dimData: {
          radius: 35,
          var: 65
        }
      }]
    }, {
      ID: 1,
      type: 'circle',
      Name: 'Mat',
      MoreData: [{
        dataID: 678,
        dimData: {
          radius: 40,
          var: 30
        }
      }, {
        dataID: 91011,
        dimData: {
          radius: 50,
          var: 50
        }
      }]
    }];
    

    var doSomething = function(array, IDVal, dataIDVal, RadiusVal) {
    
      //Search array for ID and then dataID and then set the value of that dataID's Radius to RadiusVal
      for (var i = 0; i < array.length; i++) {
        if (array[i].ID == IDVal) {
          for (var j = 0; j < array[i].MoreData.length; j++) {
            if (array[i].MoreData[j].dataID == dataIDVal) {
                console.log('Radius Before: ' +  array[i].MoreData[j].dimData.radius);
              array[i].MoreData[j].dimData.radius = 20000;
              console.log('Radius After: ' +  array[i].MoreData[j].dimData.radius);
            }
    
          }
    
        }
    
      }
    
    }
    doSomething(data, 0, 345, 100);
    console.log(data[0]);

I want to first search for the correct ID, then get the correct dataID to change the dimData.Radius.

Is there a more efficient way to do this? Needless to say, the data array can be very large and the MoreData array also contains more values (as does dimData). I was wondering if there is a faster way to achieve the above result.

EDIT: To answer a few questions, the only thing guaranteed is that the ID value will always be structured so that it increments by 1 everytime, but I don't believe the data is sorted otherwise. However, I would appreciate an answer assuming the dataset is sorted too.

EDIT 2: Attempted a solution using .filter, but ended up with several functions nested inside each other which just looked confusing.

If anyone wants that soltuion, its here: How do I pass an extra parameter to the callback function in Javascript .filter() method?

Link on JS Fiddle if Code Snippet doesn't work (I'm new): https://jsfiddle.net/53pa2xst/

TcoWhite
  • 1
  • 1

2 Answers2

0

Using nested loops is very costly in terms of time complexity O(n^2) A better approach is by simplyfing it to O(n) like this

var data = [{
    ID: 0,
    type: 'circle',
    Name: 'Tom',
    MoreData: [{
        dataID: 123,
        dimData: {
            radius: 25,
            var: 15
        }
    }, {
        dataID: 345,
        dimData: {
            radius: 35,
            var: 65
        }
    }]
}, {
    ID: 1,
    type: 'circle',
    Name: 'Mat',
    MoreData: [{
        dataID: 678,
        dimData: {
            radius: 40,
            var: 30
        }
    }, {
        dataID: 91011,
        dimData: {
            radius: 50,
            var: 50
        }
    }]
}];


var doSomething = function (array, IDVal, dataIDVal, RadiusVal) {
    let list = {};

    array.map((ar, pos) => {
        list[ar.ID] = pos;
    })

    console.log("before : ", array[0].MoreData)
    array[list[IDVal]].MoreData
    .filter(a => a.dataID == dataIDVal)[0].dimData.radius = 20000;
    console.log("After : ", array[0].MoreData)
}
doSomething(data, 0, 345, 100);

You may think to add some validators to check if Ids exists.

abnaceur
  • 252
  • 1
  • 2
0

I'm unsure as to what size your array would have to reach in order for you to notice a slow down when filtering your array, so you may not practically need another structure.

As far as I know, Array.prototype.filter will be O(n). If all you're doing with data is looking up values, then transforming it to a hash-map/object would be more performant – more along the lines of O(1).

e.g.

var data = {
  0: {
    type: 'circle',
    Name: 'Tom',
    MoreData: {
      123: {
        dimData: {
          radius: 25,
          var: 15
        }
      }, {
      345: {
        dimData: {
          radius: 35,
          var: 65
        }
      }
    }      
  }

In your search function you could access the structure like

let shape = data[IdVal]
let moreData = shape[dataIdVal]
let radius = moreData['radius']

Whether you use only this structure is purely dependent on your access pattern. If it remains that you're only picking our certain elements based on their Id then this would be a more efficient option. However, if you're filtering/searching or doing any aggregate work across the entire structure you'd probably be better off with an array-based structure and filtering. (if you're interested look up "balanced binary trees" or "treaps" as another potential solution)

SuperJumbo
  • 519
  • 3
  • 13