如何将该对列表转换为包含数组数组的对象?

时间:2019-08-03 03:08:07

标签: c++ arrays list arraylist std-pair

我有一个成对的列表,每对都有两个整数值。 如何将这对对转换为包含类似于以下edge []中显示的边数组的对象?我已经创建了一个Graph类,但是为了使用它,我需要这些对,它们将是我的边缘,被转换为一个数组数组,其中数组中的每个数组将容纳一对两个整数值。

这是我的列表,其中包含成对的整数值:

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

这是我创建的用于容纳两个边缘的结构:

struct Edge {
    int source
    int destination;
};

这个边缘数组是我希望将对对转换为的示例:

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

如果我需要对问题的特定部分更加具体,请让我知道,我将很乐于阐述。谢谢

3 个答案:

答案 0 :(得分:1)

OP在评论中回答了有关可能的实现方式的其他答案。

在原始问题中说:

  • OP的列表中包含数据list<pair<unsigned int, unsigned int> > myList;
  • OP希望使用具有2个成员的结构在图形中使用
  • OP希望将列表转换为数组

我认为OP的想法是拥有一种持有价值观的结构,这是一种合理的方法。我们有一个图,该图包含多个边。非常合理。

因此,让我们定义一个Graph类,然后添加一个边数组。但是由于我们使用的是C ++,因此我们不会使用普通的C-Style数组,而是使用std::vector

如果我们使用struct Edge的向量,则可以使用与列表相同的方式:

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

即使将原始列表封装在Graph类中,我们也可以轻松地将其转换为此类向量。有许多可能的实现。我展示了可能最受欢迎的3个版本。

  • 使用迭代器。那将是C ++ 11之前的解决方案
  • 循环的范围基准。自C ++ 1起可用。易懂易读
  • 使用std::transform进行翻译。也许是“更现代的” C ++解决方案

请参阅

#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;
}

答案 1 :(得分:0)

您为什么不使用向量呢?它们只是动态数组。

您可以做这样的事情。

class Edge 
{
public:
    //your 2d array. you can access values by doing edges[x][y]
    std::vector< std::vector<unsigned int> > edges;

    //To initialize you could create a constructor like this
    Edge(list<pair<unsigned int, unsigned int> > myList)
    {
        while(myList.size() > 0)
        {
            vector<unsigned int> temp;
            temp.push_back(myList.front().first);
            temp.push_back(myList.front().second);
            edges.push_back(temp);
            myList.pop_front();
        }
    }
}

我没有做任何封装,只是分享了创建对象的想法。

答案 2 :(得分:0)

PaulMcKenzie的评论似乎是最好的解决方案,而不是维护两个容器(std :: list和array / vector),您只能使用std::vector<Edge>

std::vector <Edge> vec{ { 0, 1 },{ 1, 2 },{ 2, 0 },{ 2, 1 } };    
int main() {
    std::cout << vec[0].source << " " << vec[0].destination ;
    for (auto e : vec) {
       e.source = e.destination = 0;
    }
}