1
\$\begingroup\$

Is there a better way than using 2 for loops and 2 if statements deep?

jsfiddle:

https://jsfiddle.net/bobbyrne01/bmnk9bLz/

Code:

var documentsInDatabase = [{
  id: '1',
  revision: '1'
}, {
  id: '2',
  revision: '1'
}, {
  id: '3',
  revision: '1'
}];

// incorrect revision of document with id of 1, and non-existent document of id 4
var requestedDocuments = [{
  id: '1',
  revision: '2'
}, {
  id: '4',
  revision: '1'
}];

var result = {
  ids_not_found: [],
  revision_mismatches: []
};

// 4 nested blocks deep
for (var i = 0; i < documentsInDatabase.length; i++) {
  for (var j = 0; j < requestedDocuments.length; j++) {
    if (documentsInDatabase[i].id === requestedDocuments[j].id) {
      if (documentsInDatabase[i].revision !== requestedDocuments[j].revision) {
        result.revision_mismatches.push(requestedDocuments[j].id);
      }

      requestedDocuments.splice(j, 1);
      break;
    }
  }
}

for (var l = 0; l < requestedDocuments.length; l++) {
  result.ids_not_found.push(requestedDocuments[l].id);
}

document.getElementById('container').innerHTML = JSON.stringify(result, null, 2);
\$\endgroup\$
2
\$\begingroup\$

When you have code that starts to look like this, it's a sign that you need to write more functions to abstract some things away. You might put the code inside the two for loops into its own function, for example.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

A cheap trick is to check for != instead of ==. e.g. this gets rid of one level of indentation:

for (var i = 0; i < documentsInDatabase.length; i++) {
        for (var j = 0; j < requestedDocuments.length; j++) {
                if (documentsInDatabase[i].id != requestedDocuments[j].id)
                        continue;

                if (documentsInDatabase[i].revision !== requestedDocuments[j].revision) {
                        result.revision_mismatches.push(requestedDocuments[j].id);
                }

                requestedDocuments.splice(j, 1);
                break;
        }
}

Apologies if != isn't the opposite if ===, I'm not a JS programmer.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

You should split your code into smaller parts that better describe what they do.

Use a hashmap for your existing documents to simplify/speed up lookups.

The following version supports multiple revisions for the same doc id in the database. It can probably be simplified more, but this code should be pretty easy to read and maintain:

var documentsInDatabase = [
    { id: '1', revision: '1' }, 
    { id: '2', revision: '1' }, 
    { id: '3', revision: '1' }
];

// incorrect revision of document with id of 1, and non-existent document of id 4 
var requestedDocuments = [
    { id: '1', revision: '2' }, 
    { id: '4', revision: '1' }
]; 



var docMap = createMapOf(documentsInDatabase);

var result = matchDocs(requestedDocuments, docMap);

var container = document.getElementById('container');
container.innerHTML = JSON.stringify(result, null, 2);


function createMapOf(docs) {
    var map = {};
    for(var i=0; i<docs.length; i++) {
        var doc = docs[i];
        if (map[doc.id] === undefined)
            map[doc.id] = { };
        map[doc.id][doc.revision] = doc;
    }
    return map;
}

function matchDocs(docs, docMap) {
    var result = emptyResults();
    for(var i=0; i<docs.length; i++) {
        var doc = docs[i];

        if(!mapHasId(doc, docMap))
            result.ids_not_found.push(doc.id);
        else if(!mapHasRev(doc, docMap))
            result.revision_mismatches.push(doc.id);
    }
    return result;
}

function emptyResults() {
    return { 
        ids_not_found: [],
        revision_mismatches: [] 
    }; 
}

function mapHasId(doc, docMap) {
    return docMap[doc.id] !== undefined;
}

function mapHasRev(doc, docMap) {
    return docMap[doc.id][doc.revision] !== undefined;
}
| improve this answer | |
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.