2

If my json file is this:

[
 {
  "friendName": "Ann",
  "birthday": "1990-04-19",
  "favoriteColor": "Purple",
 },
 {
  "friendName": "Rachel",
  "birthday": "1995-7-05",
  "favoriteColor": "Pink",
 },
 {
  "friendName": "Max",
  "birthday": "1993-10-07",
  "favoriteColor": "Purple",
 },
 {
  "friendName": "Bob",
  "birthday": "1992-02-20",
  "favoriteColor": "Red",
 }
]

How could I obtain the youngest girl's name? (As in sorting the girls' birthday strings in descending order, then grabbing the first object in the list (1993-10-07) and printing their name).

I am using JSON for Modern C++ (https://github.com/nlohmann/json) and Xcode (version 6).

In my project, I will not know the amount of objects I will have. Is there a way to sort these strings by comparison?

1 Answers1

4

A nice thing about the nlohmann/json is that it offers STL-like access, which allows for using a nlohmann::json with most of the functions in <algorithm>.

In particular, std::min_element() might come in handy when looking for the min element in a container... given a custom comparison function :)

In the following code, I used the dob_comp() lambda as a comparison function to compare persons by their dates of birth (dob). The youngest person is, therefore, the one with the "minimum date of birth".

[run it online (close main.cpp if it's open, click compile, then execute)]

// compile with: g++ --std=c++11 this_file.cpp -o your_executable_name

#include <algorithm>
#include <ctime>
#include <iomanip>
#include <iostream>

#include "json.hpp"

int main()
{
    // sample json object
    nlohmann::json j = nlohmann::json::parse("["
        "{"
        " \"friendName\": \"Ann\","
        " \"birthday\": \"1990-04-19\","
        " \"favoriteColor\": \"Purple\""
        "},"
        "{"
        " \"friendName\": \"Rachel\","
        " \"birthday\": \"1995-07-05\","
        " \"favoriteColor\": \"Pink\""
        "},"
        "{"
        " \"friendName\": \"Max\","
        " \"birthday\": \"1993-10-07\","
        " \"favoriteColor\": \"Purple\""
        "},"
        "{"
        " \"friendName\": \"Bob\","
        " \"birthday\": \"1992-02-20\","
        " \"favoriteColor\": \"Red\""
        "}"
    "]");

    // converts a date string to a std::tm structure
    // assumes the string is formatted as "YYYY-MM-DD"
    const auto str_to_time = [] (std::string str) {
        std::tm tm;
        // http://stackoverflow.com/a/21021900
        //std::stringstream ss(str);
        //ss >> std::get_time(&tm, "%Y-%m-%d");
        strptime(str.c_str(), "%Y-%m-%d", &tm);
        return tm;
    };

    // simplistic comparison of std::tm structures -- compares only the (year,month,day)
    const auto time_comp = [] (const std::tm& t1, const std::tm& t2) {
        if (t1.tm_year < t2.tm_year)
        {
            return true;
        }
        else if (t1.tm_year > t2.tm_year)
        {
            return false;
        }
        else if (t1.tm_mon < t2.tm_mon)
        {
            return true;
        }
        else if (t1.tm_mon > t2.tm_mon)
        {
            return false;
        }
        else if (t1.tm_mday < t2.tm_mday)
        {
            return true;
        }
        else if (t1.tm_mday > t2.tm_mday)
        {
            return false;
        }
        else
        {
            return true;
        }
    };

    // I didn't have time to read too much of the "json.hpp" header
    // so I used a quick "decltype()" to find the iterator type
    using json_iterator_type = decltype(*j.begin());

    // compares the DatesOfBirth (dob) of two persons
    const auto dob_comp = [&str_to_time, &time_comp] (const json_iterator_type p1, const json_iterator_type p2) {
        std::string dob1 = p1["birthday"];
        std::string dob2 = p2["birthday"];

        auto ttm1 = str_to_time(dob1);
        auto ttm2 = str_to_time(dob2);

        return time_comp(ttm1, ttm2);
    };

    // know your <algorithm>'s :)
    const auto youngest = *std::min_element(j.begin(), j.end(), dob_comp);

    std::cout << "The youngest person is: " << youngest << std::endl;
}

Note: if you want to sort the elements, you can use std::sort() like this:

std::sort(j.begin(), j.end(), dob_comp);

Note2: check out jq if you need a tool for processing json files.

maddouri
  • 3,737
  • 5
  • 29
  • 51
  • Did you try out the sorting as suggested in your Note? According to [this issue](https://github.com/nlohmann/json/issues/106) the underlying structure of `json` uses a `std::map`, hence `std::sort` would not work. – Patrick Dec 19 '19 at 11:48