Question

I have a std::map that I generate from a json and a map that I generate from sqlite.

I want to compare the two maps and make changes to the sqlite so that it matches the json. I originally used the map.find(key) method through both maps to figure out what to add and what to delete but my friend told me that map was sorted from least to greatest key and so I could just run through it once.

I came up with two methods. Do you have any advice on which algorithm would be preferred and why? I am thinking the one I have uncommented is faster as (and please correct me if I'm wrong) I believe the uncommented one is O(n) worst case while the latter is O(n^2) worst case.

Also, my friend had mentioned that I didn't need the second 'clean up' while loop to reconcile the remaining sqlMap items, but I really think I need it. Is he right?

Here's my code:

void SqlSync::syncEvents() {
    int added = 0;
    int replaced = 0;
    int deleted = 0;
    int skipped = 0;

    // get categories from Apsiva
    std::map<int, Event> jsonMap = _apsivaRest->getEvents();

    // get categories from sqlite
    std::map<int, Event> sqlMap = _sqliteConnection->getEventMap(true);

    // COMPARE
    map<int, Event>::iterator jsonIter = jsonMap.begin();
    map<int, Event>::iterator sqlIter = sqlMap.begin();

    while (jsonIter != jsonMap.end() && sqlIter != sqlMap.end()) {
        int jsonId = jsonIter->first;
        Event jsonObj = jsonIter->second;
        int sqlId = sqlIter->first;

        if (jsonId < sqlId) {
            // add
            _sqliteConnection->addEvent(jsonObj);
            ++added;
            ++jsonIter;
        } else if (jsonId > sqlId) {
            // remove
            _sqliteConnection->deleteEvent(sqlId);
            ++deleted;
            ++sqlIter;
        } else {
            if (jsonObj.isNewerThan(sqlIter->second)) {
                _sqliteConnection->updateEvent(jsonObj);
                ++replaced;
            } else {
                // ignore
                cout << "Skipped event b/c not newer" << endl; // delete when verified
                ++skipped;
            }
            ++jsonIter;
            ++sqlIter;
        }
    }

//    int jRemaining = std::distance(jsonIter, jsonMap.end());
//    int sRemaining = std::distance(sqlIter, sqlMap.end());

    // add remaining jsonMap Objects
    while (jsonIter != jsonMap.end()) {
        Event jsonObj = jsonIter->second;
        _sqliteConnection->addEvent(jsonIter->second);
        ++added;
        ++jsonIter;
    }
    // delete remaining sqlMap Objects
    while (sqlIter != sqlMap.end()) {
        _sqliteConnection->deleteEvent(sqlIter->first);
        ++deleted;
        ++sqlIter;
    }

    // OLD WAY TO COMPARE.

//    // add/replace keys found in json
//    for (map<int, Event>::const_iterator jsonIter = jsonMap.begin(); jsonIter != jsonMap.end(); ++jsonIter) {
//        map<int,Event>::const_iterator it = sqlMap.find(jsonIter->first);
//        Event jsonObj = jsonIter->second;
//        if (it != sqlMap.end()) {
//            Event sqlObj = it->second;
//            if (jsonObj.isNewerThan(sqlObj)) {
////                _sqliteConnection->updateEvent(jsonObj);
//                ++replaced;
//            } else {
//                // ignore
//                cout << "Skipped category b/c not newer" << endl; // delete when verified
//                ++skipped;
//            }
//        } else {
////            _sqliteConnection->addEvent(jsonObj);
//            ++added;
//        }
//    }
//
//    // delete sqlmap CategoryRows not in jsonMap
//    for (map<int, Event>::const_iterator sqlObj = sqlMap.begin(); sqlObj != sqlMap.end(); ++sqlObj) {
//        if (jsonMap.find(sqlObj->first) == jsonMap.end()) {
////            _sqliteConnection->deleteEvent(sqlObj->first);
//            ++deleted;
//        }
//    }

#ifdef DEBUG
    cout << "CATEGORIES SYNC:" << endl;
    cout << "---------------" << endl;
    cout << "Added: " << added << " | Replaced: " << replaced
    << " | Deleted: " << deleted << " | Skipped: " << skipped << endl;
#endif //DEBUG
}
Was it helpful?

Solution

  1. The uncommented way is more efficient. The complexity will be O(n+m) when n and m are sizes of json and SQLite maps.
  2. You will need the last loop, since when you exit the first loop you don't know which map end you reached first. Consider next case - json map has ids 1,2,4,5 and SQLite has ids 1,2,6,7. You will need the last loop in order to delete items 6 and 7.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top