如何将这个成对列表转换为包含数组数组的对象?
How can I convert this list of pairs into an object that contains an array of arrays?
我有一个对列表,每对包含两个整数值。
我怎样才能将这个成对列表转换成一个包含边数组的对象,类似于下面的 edges[] 中显示的内容?我创建了一个图 class,但为了使用它,我需要这些对,它们将是我的边,转换成一个数组数组,其中数组中的每个数组将包含一对两个整数值.
这是我的包含成对整数值的列表:
list<pair<unsigned int, unsigned int> > myList;
这是我创建的用于容纳两条边的结构:
struct Edge {
int source
int destination;
};
这个边数组是我希望将我的对列表转换成的示例:
Edge edges[] =
{
{ 0, 1 }, { 1, 2 }, { 2, 0 }, { 2, 1 }
};
如果我需要更具体地说明问题的特定部分,请告诉我,我很乐意详细说明。谢谢
为什么不使用矢量呢?它们只是动态数组。
你可以这样做。
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();
}
}
}
我没有做任何封装,只是分享创建对象的想法
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;
}
}
OP 在对其他答案的评论中询问了可能的实现方式。
原题中是这样写的:
- OP 有一个包含数据的列表
list<pair<unsigned int, unsigned int> > myList;
- OP 想要在图表中使用具有 2 个成员的结构
- OP 想把列表转成数组
我认为 OP 的想法是有一个结构来保存值是一个合乎逻辑的好方法。我们有一个图,该图包含多个边。很有道理。
所以,让我们定义一个 class 图,我们将添加一个边数组。但是因为我们在 C++ 中,我们不会使用普通的 C 风格数组,而是 std::vector
.
如果我们要使用struct Edge的vector,它可以像列表一样使用:
std::vector<Edge> sameAsList{ { 0U, 1U }, { 1U, 2U }, { 2U, 0U }, { 2U, 1U } };
我们可以很容易地将原始列表转换成这样的向量,即使它被封装在一个图形中 class。有许多可能的实现。我展示了可能最受欢迎的 3 个版本。
- 使用迭代器。那将是 C++11 之前的解决方案
- 循环的范围基数。自 C++1 起可用。易于理解和阅读
- 与
std::transform
的转型。也许 "more modern" 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;
}
我有一个对列表,每对包含两个整数值。 我怎样才能将这个成对列表转换成一个包含边数组的对象,类似于下面的 edges[] 中显示的内容?我创建了一个图 class,但为了使用它,我需要这些对,它们将是我的边,转换成一个数组数组,其中数组中的每个数组将包含一对两个整数值.
这是我的包含成对整数值的列表:
list<pair<unsigned int, unsigned int> > myList;
这是我创建的用于容纳两条边的结构:
struct Edge {
int source
int destination;
};
这个边数组是我希望将我的对列表转换成的示例:
Edge edges[] =
{
{ 0, 1 }, { 1, 2 }, { 2, 0 }, { 2, 1 }
};
如果我需要更具体地说明问题的特定部分,请告诉我,我很乐意详细说明。谢谢
为什么不使用矢量呢?它们只是动态数组。
你可以这样做。
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();
}
}
}
我没有做任何封装,只是分享创建对象的想法
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;
}
}
OP 在对其他答案的评论中询问了可能的实现方式。
原题中是这样写的:
- OP 有一个包含数据的列表
list<pair<unsigned int, unsigned int> > myList;
- OP 想要在图表中使用具有 2 个成员的结构
- OP 想把列表转成数组
我认为 OP 的想法是有一个结构来保存值是一个合乎逻辑的好方法。我们有一个图,该图包含多个边。很有道理。
所以,让我们定义一个 class 图,我们将添加一个边数组。但是因为我们在 C++ 中,我们不会使用普通的 C 风格数组,而是 std::vector
.
如果我们要使用struct Edge的vector,它可以像列表一样使用:
std::vector<Edge> sameAsList{ { 0U, 1U }, { 1U, 2U }, { 2U, 0U }, { 2U, 1U } };
我们可以很容易地将原始列表转换成这样的向量,即使它被封装在一个图形中 class。有许多可能的实现。我展示了可能最受欢迎的 3 个版本。
- 使用迭代器。那将是 C++11 之前的解决方案
- 循环的范围基数。自 C++1 起可用。易于理解和阅读
- 与
std::transform
的转型。也许 "more modern" 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;
}