Search code examples
c++arrayslistarrayliststd-pair

How can I convert this list of pairs into an object that contains an array of arrays?


I have a list of pairs, and each pair holds two integer values. How can I convert this list of pairs into an object that contains an array of edges similar to what is presented in edges[] below? I have created a Graph class, but in order to use it, I need these pairs, which will be my edges, converted into an array of arrays, where each array within the array will hold one pair of two integer values.

This is my list containing the pairs of integer values:

list<pair<unsigned int, unsigned int> > myList;

This is the struct i created to hold the two edges:

struct Edge {
    int source
    int destination;
};

This array of edges is an example of what I want my list of pairs to be converted into:

Edge edges[] =
        {
            { 0, 1 }, { 1, 2 }, { 2, 0 }, { 2, 1 }
        };

If I need to be more specific about a particular part of the question, let me know and I will be happy to elaborate. Thanks


Solution

  • OP asked in comment to other answer on how possible implementations could look like.

    In the original question it was stated:

    • OP has a list with data list<pair<unsigned int, unsigned int> > myList;
    • OP wants to use a struct with 2 members for usage in a graph
    • OP wants to convert the list into an array

    I think OP's idea to have a struct to hold the values is a logical good approach. We have a Graph and the Graph contains several edges. Very reasonable.

    So, let us define a class Graph and we will add an array of edges. But since we are in C++, we will not use a plain C-Style array, but a std::vector.

    If we would use the vector of struct Edge, it could be used in the same way as the list:

    std::vector<Edge> sameAsList{ { 0U, 1U }, { 1U, 2U }, { 2U, 0U }, { 2U, 1U } };
    

    And we can easily convert the original list into such vector, even, if it is encapsulated in a Graph class. There are many possible implementations. I show the maybe most popular 3 versions.

    • Using iterators. That would be the pre C++11 solution
    • Range base for loop. Available since C++1. Easy to understand and easy to read
    • Transormation with std::transform. Maybe the "more modern" C++ solution

    Please see

    #include <vector>
    #include <list>
    #include <utility>
    #include <algorithm>
    #include <iostream>
    #include <iterator>
    
    // Define aliases. To make reading easier
    using PairOfUint = std::pair<unsigned int, unsigned int>;
    using ListOfPairs = std::list<PairOfUint>;
    
    // Our struct for edges
    struct Edge {
        Edge() {}
        Edge(unsigned int s, unsigned int d) : source(s), destination(d) {}
        friend std::ostream& operator << (std::ostream& os, const Edge& e) { return os << e.source << " " << e.destination; }
    
        unsigned int source{};
        unsigned int destination{};
    };
    
    
    class Graph
    {
    public:
        Graph() : edges() {}
    
        // 3 differnt conversion functions from list of pair to vector of struct. All have the same result
        void add1(ListOfPairs& lop);
        void add2(ListOfPairs& lop);
        void add3(ListOfPairs& lop);
    
        // Reset edges vector to empty 
        void clearEdges() { edges.clear(); }
    
        // Inserter. For this example, just print edges
        friend std::ostream& operator << (std::ostream& os, const Graph& g) {
            std::copy(g.edges.begin(), g.edges.end(), std::ostream_iterator<Edge>(os, "\n")); return os;
        }
    
    protected:
        std::vector<Edge> edges{};
    };
    
    void Graph::add1(ListOfPairs& lop)
    {
        for (ListOfPairs::const_iterator cIterLop = lop.cbegin(); cIterLop != lop.cend(); ++cIterLop)
            edges.emplace_back(Edge(cIterLop->first, cIterLop->second));
    }
    
    void Graph::add2(ListOfPairs& lop)
    {
        for (const PairOfUint& poui : lop)
            edges.emplace_back(Edge(poui.first, poui.second));
    }
    
    void Graph::add3(ListOfPairs& lop)
    {
        std::transform(lop.begin(), lop.end(), std::back_inserter(edges), [](const PairOfUint & poui) {
            return Edge(poui.first, poui.second); });
    }
    
    
    ListOfPairs myList{ { 0U, 1U }, { 1U, 2U }, { 2U, 0U }, { 2U, 1U } };
    
    int main()
    {
        Graph graph{};
    
        graph.add1(myList);
        std::cout << "\nVersion1 with iterators:\n" << graph;
    
        graph.clearEdges();
        graph.add2(myList);
        std::cout << "\n\nVersion2 with range based for:\n" << graph;
    
        graph.clearEdges();
        graph.add3(myList);
        std::cout << "\n\nVersion3 with std::transform for:\n" << graph;
    
        return 0;
    }