1
\$\begingroup\$

Task description:

Search the highest ID within a given JSON-structure: An array with objects as elements. Every object has a property "ID".

Then increment the highest ID and return it as a result. For to become the next ID used.

There can be gaps within the given data-structure (because of prior delete operations). This gaps aren't allowed to use. It shall always be: Highest ID plus 1.

I have currently two different implementations for a solution.

The first solution is a more functional approach:

var testData = [
  {"id":1,"first_name":"Paul","last_name":"Myers","email":"pmyers0@vk.com"},
  {"id":2,"first_name":"Donald","last_name":"Cooper","email":"dcooper1@ehow.com"},
  {"id":3,"first_name":"Linda","last_name":"Watson","email":"lwatson2@chron.com"},
  {"id":5,"first_name":"Timothy","last_name":"Nguyen","email":"tnguyen4@discuz.net"},
  {"id":6,"first_name":"Frances","last_name":"Griffin","email":"fgriffin5@patch.com"},
  {"id":7,"first_name":"Julia","last_name":"Kelly","email":"jkelly6@fema.gov"},
  {"id":8,"first_name":"Ann","last_name":"Ruiz","email":"aruiz7@amazon.com"},
  {"id":9,"first_name":"Donald","last_name":"Barnes","email":"dbarnes8@tumblr.com"},
  {"id":10,"first_name":"Justin","last_name":"Parker","email":"jparker9@marriott.com"},
  {"id":11,"first_name":"Todd","last_name":"Medina","email":"tmedinaa@dailymail.co.uk"},
  {"id":12,"first_name":"Donald","last_name":"Welch","email":"dwelchb@eventbrite.com"},
  {"id":14,"first_name":"Cynthia","last_name":"Ramirez","email":"cramirezd@hubpages.com"},
  {"id":15,"first_name":"Kathleen","last_name":"Andrews","email":"kandrewse@techcrunch.com"},
  {"id":17,"first_name":"Joseph","last_name":"Larson","email":"jlarsong@soundcloud.com"},
  {"id":18,"first_name":"Joseph","last_name":"Hicks","email":"jhicksh@forbes.com"},
  {"id":91,"first_name":"Irene","last_name":"Johnson","email":"ijohnson2i@sphinn.com"},
  {"id":92,"first_name":"Rebecca","last_name":"Grant","email":"rgrant2j@soundcloud.com"},
  {"id":93,"first_name":"Donald","last_name":"Ortiz","email":"dortiz2k@bloglovin.com"},
  {"id":94,"first_name":"Howard","last_name":"Perry","email":"hperry2l@dot.gov"},
];

function hightestIdPlusOne(data) {
  
  if (typeof data !== 'object') {
    throw new Error ('Object expected. But ' + typeof data + ' found.');
  }
  
  if (data === null) {
    throw new Error ('Object expected. But null found.');
  }
  
  var ids = data.map(function(obj) {
    
    if (!obj.id) {
        throw new Error ('Id property expected but undefined found.');
    }
    
    return obj.id;
  });
  
  return Math.max.apply(null, ids) + 1;
}

console.log(hightestIdPlusOne(testData));

The second solution uses the MinMax-algorithm:

var testData = [
  {"id":1,"first_name":"Paul","last_name":"Myers","email":"pmyers0@vk.com"},
  {"id":2,"first_name":"Donald","last_name":"Cooper","email":"dcooper1@ehow.com"},
  {"id":3,"first_name":"Linda","last_name":"Watson","email":"lwatson2@chron.com"},
  {"id":5,"first_name":"Timothy","last_name":"Nguyen","email":"tnguyen4@discuz.net"},
  {"id":6,"first_name":"Frances","last_name":"Griffin","email":"fgriffin5@patch.com"},
  {"id":7,"first_name":"Julia","last_name":"Kelly","email":"jkelly6@fema.gov"},
  {"id":8,"first_name":"Ann","last_name":"Ruiz","email":"aruiz7@amazon.com"},
  {"id":9,"first_name":"Donald","last_name":"Barnes","email":"dbarnes8@tumblr.com"},
  {"id":10,"first_name":"Justin","last_name":"Parker","email":"jparker9@marriott.com"},
  {"id":11,"first_name":"Todd","last_name":"Medina","email":"tmedinaa@dailymail.co.uk"},
  {"id":12,"first_name":"Donald","last_name":"Welch","email":"dwelchb@eventbrite.com"},
  {"id":14,"first_name":"Cynthia","last_name":"Ramirez","email":"cramirezd@hubpages.com"},
  {"id":15,"first_name":"Kathleen","last_name":"Andrews","email":"kandrewse@techcrunch.com"},
  {"id":17,"first_name":"Joseph","last_name":"Larson","email":"jlarsong@soundcloud.com"},
  {"id":18,"first_name":"Joseph","last_name":"Hicks","email":"jhicksh@forbes.com"},
  {"id":91,"first_name":"Irene","last_name":"Johnson","email":"ijohnson2i@sphinn.com"},
  {"id":92,"first_name":"Rebecca","last_name":"Grant","email":"rgrant2j@soundcloud.com"},
  {"id":93,"first_name":"Donald","last_name":"Ortiz","email":"dortiz2k@bloglovin.com"},
  {"id":94,"first_name":"Howard","last_name":"Perry","email":"hperry2l@dot.gov"},
];

function hightestIdPlusOne(data) {
  var max = 0;
  
  if (typeof data !== 'object') {
    throw new Error ('Object expected. But ' + typeof data + ' found.');
  }
  
  if (data === null) {
    throw new Error ('Object expected. But null found.');
  }
  
  data.forEach(function(obj) {
    
    if (!obj.id) {
        throw new Error ('Id property expected but undefined found.');
    }
    
    if (obj.id > max) {
      max = obj.id;
    }
  });

  return ++max;
}

console.log(hightestIdPlusOne(testData));

Both solutions seem to provide a correct result.

But I would like to know:

  • Which approach shall I prefer and for what reasons?

  • Is my checking of the given data-structure / parameter sufficient? So that incorrect results become impossible. Or does it have to be improved?

Looking forward to read your comments concerning the two questions. Any other hints I would appreciate too.

\$\endgroup\$
  • \$\begingroup\$ The second one doesn't create an intermediate array, and thus is obviously better. I'm not sure why the first one is even an option to consider. \$\endgroup\$ – wOxxOm Oct 16 '16 at 15:19
  • \$\begingroup\$ @wOxxOm While I agree in this case, it's worth noting that your reasoning (in the general case) is incorrect imo. Often doing something like creating a needless intermediate array will make the code shorter and more readable, and It's quite possible that worrying about the intermediate array is a premature optimization for many applications, so it's quite reasonable to write less optimized code in the name of readability. This happens not to be this case here... \$\endgroup\$ – Jonah Oct 16 '16 at 15:54
  • \$\begingroup\$ You should use reduce here: testData.reduce((m,x) => Math.max(x.id, m), 0). Also consider breaking your validation out into a separate step. This means you'd have to perform the loop twice, but the solution will still be \$O(n)\$ and you'll have a better separation of concerns and more readable code. And you can alway introduce a convenience functions that combines the validation and the "next id" calculation together. \$\endgroup\$ – Jonah Oct 16 '16 at 15:59
  • \$\begingroup\$ This is a trivial task and its most readable form is a plain for loop, also the fastest. \$\endgroup\$ – wOxxOm Oct 16 '16 at 16:33
  • \$\begingroup\$ Both solutions will fire a TypeError rather a custom Error if data is a plain object. You should add something like if (!Array.isArray(data)) { throw new Error ('...);. \$\endgroup\$ – cFreed Oct 16 '16 at 23:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.