Yaml-cpp:在发射器中的每个新地图之前禁用自动 begindoc (---)
Yaml-cpp: Disable automatic begindoc (---) before each new map in emitter
我正在使用 yaml-cpp 生成一个结构日志文件,我可以稍后再次读回。它可能不是这项工作的最佳工具,但现在我只需要一些入门工具。
但是,我遇到了一些问题,如本示例输出所示:
---
0: 42
---
1: 42
---
2: 42
---
3: 42
---
4: 42
...
我想要的是这个:
---
0: 42
1: 42
2: 42
3: 42
4: 42
...
这是生成它的代码:
YAML::Emitter res;
res << YAML::BeginDoc;
for (int i = 0; i < 5; i++)
{
res << YAML::BeginMap
<< YAML::Key << i
<< YAML::Value << 42
<< YAML::EndMap;
}
res << YAML::EndDoc;
std::cout << res.c_str() << std::endl;
我查看了源代码 (https://github.com/jbeder/yaml-cpp/blob/master/src/emitter.cpp) 并发现了这一点:
// EmitBeginDoc
void Emitter::EmitBeginDoc() {
if (!good())
return;
if (m_pState->CurGroupType() != GroupType::NoType) {
m_pState->SetError("Unexpected begin document");
return;
}
if (m_pState->HasAnchor() || m_pState->HasTag()) {
m_pState->SetError("Unexpected begin document");
return;
}
if (m_stream.col() > 0)
m_stream << "\n";
m_stream << "---\n";
m_pState->StartedDoc();
}
但是我从这里所做的超出了我的范围。一方面,我可以做一些小改动,然后在将输出写入文件之前将所有 --- 从输出中删除(当然,第一个除外),但另一方面,我只是假设我一定忽略了一些细节可以更优雅地解决这个问题。
编辑:
我的例子并没有证明地图的合理性,所以我会进一步解释一下。
我正在为大量图像存储一些元信息。当我读回它们时,我想直接访问每个图像的信息,即 myyaml[frame_id]["algorithm_2"]["result_x"] 其中 frame_id 可能是例如3. 如果每个图像在文件中都有自己的文档,我不知道如何执行此操作,除非每次查找都遍历整个文件。这些图像 而不是 必须是从 0 到 number_of_images 的连续序列。
编辑 2:
关于 João Augusto 编辑过的答案,这里有一个更详细的例子,但它也不起作用:
YAML::Emitter res;
res << YAML::BeginDoc;
for (int i = 3; i < 7; i++)
{
res << YAML::BeginMap
<< YAML::Key << i
<< YAML::Value
<< YAML::BeginSeq
<< YAML::BeginMap
<< YAML::Key << "Algorithm 1"
<< YAML::Value
<< YAML::BeginSeq
<< YAML::Flow
<< YAML::BeginSeq << 54*i << 42/i << 10+i << 17-i << YAML::EndSeq
<< YAML::Flow
<< YAML::BeginSeq << 6*i << 3/i << 87+i << 33-i << YAML::EndSeq
<< YAML::EndSeq
<< YAML::EndMap
<< YAML::BeginMap
<< YAML::Key << "Algorithm 2"
<< YAML::Value
<< YAML::BeginSeq
<< YAML::Flow
<< YAML::BeginSeq << 65*i << 27/i << 54+i << 76-i << YAML::EndSeq
<< YAML::Flow
<< YAML::BeginSeq << 45*i << 66/i << 98+i << 34-i << YAML::EndSeq
<< YAML::EndSeq
<< YAML::EndMap
<< YAML::EndSeq
<< YAML::EndMap;
}
res << YAML::EndDoc;
std::cout << res.c_str() << std::endl;
这是输出:
---
3:
- Algorithm 1:
- [162, 14, 13, 14]
- [18, 1, 90, 30]
- Algorithm 2:
- [195, 9, 57, 73]
- [135, 22, 101, 31]
---
4:
- Algorithm 1:
- [216, 10, 14, 13]
- [24, 0, 91, 29]
- Algorithm 2:
- [260, 6, 58, 72]
- [180, 16, 102, 30]
---
5:
- Algorithm 1:
- [270, 8, 15, 12]
- [30, 0, 92, 28]
- Algorithm 2:
- [325, 5, 59, 71]
- [225, 13, 103, 29]
---
6:
- Algorithm 1:
- [324, 7, 16, 11]
- [36, 0, 93, 27]
- Algorithm 2:
- [390, 4, 60, 70]
- [270, 11, 104, 28]
...
其中仍然有不需要的新文档语句。我需要在我的代码中更改什么才能使它们不显示?
你应该阅读 yaml 格式的文档。
您正在为每个项目创建一个地图,您想要的是这样的。
YAML::Emitter res;
res << YAML::BeginDoc << YAML::BeginMap;
for (int i = 0; i < 5; i++)
{
res << YAML::Key << i
<< YAML::Value << 42;
}
res << YAML::EndMap << YAML::EndDoc;
编辑...
你只需要按照你想要访问数据的方式编写 yaml,所以如果你这样做:
---
frame_0:
algorithm_1: 1
algorithm_2: 2
frame_1:
algorithm_1: 10
algorithm_2: 2
frame_2:
algorithm_1: 8
algorithm_2: 22
frame_3:
algorithm_1: 1
algorithm_2: 23
frame_4:
algorithm_1: 12
algorithm_2: 21
...
您可以通过以下方式访问 frame_3 中 algorithm_2 的值:
YAML::Node yaml = YAML::Load(res.c_str());
int value = yaml["frame_3"]["algorithm_2"].as<int>();
编辑...
YAML::Emitter res;
res << YAML::BeginDoc;
res << YAML::BeginMap;
for (int i = 3; i < 7; i++)
{
res << YAML::Key << i
<< YAML::Value
<< YAML::BeginSeq
<< YAML::BeginMap
<< YAML::Key << "Algorithm 1"
<< YAML::Value
<< YAML::BeginSeq
<< YAML::Flow
<< YAML::BeginSeq << 54 * i << 42 / i << 10 + i << 17 - i << YAML::EndSeq
<< YAML::Flow
<< YAML::BeginSeq << 6 * i << 3 / i << 87 + i << 33 - i << YAML::EndSeq
<< YAML::EndSeq
<< YAML::EndMap
<< YAML::BeginMap
<< YAML::Key << "Algorithm 2"
<< YAML::Value
<< YAML::BeginSeq
<< YAML::Flow
<< YAML::BeginSeq << 65 * i << 27 / i << 54 + i << 76 - i << YAML::EndSeq
<< YAML::Flow
<< YAML::BeginSeq << 45 * i << 66 / i << 98 + i << 34 - i << YAML::EndSeq
<< YAML::EndSeq
<< YAML::EndMap
<< YAML::EndSeq;
}
res << YAML::EndMap;
res << YAML::EndDoc;
这会做你想做的,你的问题是(假设你想要一个键从 3 到 7 的地图)你正在为 3、4、5、6 和 7 创建一个地图而不是一个地图使用键 3,4,...,7
我正在使用 yaml-cpp 生成一个结构日志文件,我可以稍后再次读回。它可能不是这项工作的最佳工具,但现在我只需要一些入门工具。
但是,我遇到了一些问题,如本示例输出所示:
---
0: 42
---
1: 42
---
2: 42
---
3: 42
---
4: 42
...
我想要的是这个:
---
0: 42
1: 42
2: 42
3: 42
4: 42
...
这是生成它的代码:
YAML::Emitter res;
res << YAML::BeginDoc;
for (int i = 0; i < 5; i++)
{
res << YAML::BeginMap
<< YAML::Key << i
<< YAML::Value << 42
<< YAML::EndMap;
}
res << YAML::EndDoc;
std::cout << res.c_str() << std::endl;
我查看了源代码 (https://github.com/jbeder/yaml-cpp/blob/master/src/emitter.cpp) 并发现了这一点:
// EmitBeginDoc
void Emitter::EmitBeginDoc() {
if (!good())
return;
if (m_pState->CurGroupType() != GroupType::NoType) {
m_pState->SetError("Unexpected begin document");
return;
}
if (m_pState->HasAnchor() || m_pState->HasTag()) {
m_pState->SetError("Unexpected begin document");
return;
}
if (m_stream.col() > 0)
m_stream << "\n";
m_stream << "---\n";
m_pState->StartedDoc();
}
但是我从这里所做的超出了我的范围。一方面,我可以做一些小改动,然后在将输出写入文件之前将所有 --- 从输出中删除(当然,第一个除外),但另一方面,我只是假设我一定忽略了一些细节可以更优雅地解决这个问题。
编辑: 我的例子并没有证明地图的合理性,所以我会进一步解释一下。 我正在为大量图像存储一些元信息。当我读回它们时,我想直接访问每个图像的信息,即 myyaml[frame_id]["algorithm_2"]["result_x"] 其中 frame_id 可能是例如3. 如果每个图像在文件中都有自己的文档,我不知道如何执行此操作,除非每次查找都遍历整个文件。这些图像 而不是 必须是从 0 到 number_of_images 的连续序列。
编辑 2: 关于 João Augusto 编辑过的答案,这里有一个更详细的例子,但它也不起作用:
YAML::Emitter res;
res << YAML::BeginDoc;
for (int i = 3; i < 7; i++)
{
res << YAML::BeginMap
<< YAML::Key << i
<< YAML::Value
<< YAML::BeginSeq
<< YAML::BeginMap
<< YAML::Key << "Algorithm 1"
<< YAML::Value
<< YAML::BeginSeq
<< YAML::Flow
<< YAML::BeginSeq << 54*i << 42/i << 10+i << 17-i << YAML::EndSeq
<< YAML::Flow
<< YAML::BeginSeq << 6*i << 3/i << 87+i << 33-i << YAML::EndSeq
<< YAML::EndSeq
<< YAML::EndMap
<< YAML::BeginMap
<< YAML::Key << "Algorithm 2"
<< YAML::Value
<< YAML::BeginSeq
<< YAML::Flow
<< YAML::BeginSeq << 65*i << 27/i << 54+i << 76-i << YAML::EndSeq
<< YAML::Flow
<< YAML::BeginSeq << 45*i << 66/i << 98+i << 34-i << YAML::EndSeq
<< YAML::EndSeq
<< YAML::EndMap
<< YAML::EndSeq
<< YAML::EndMap;
}
res << YAML::EndDoc;
std::cout << res.c_str() << std::endl;
这是输出:
---
3:
- Algorithm 1:
- [162, 14, 13, 14]
- [18, 1, 90, 30]
- Algorithm 2:
- [195, 9, 57, 73]
- [135, 22, 101, 31]
---
4:
- Algorithm 1:
- [216, 10, 14, 13]
- [24, 0, 91, 29]
- Algorithm 2:
- [260, 6, 58, 72]
- [180, 16, 102, 30]
---
5:
- Algorithm 1:
- [270, 8, 15, 12]
- [30, 0, 92, 28]
- Algorithm 2:
- [325, 5, 59, 71]
- [225, 13, 103, 29]
---
6:
- Algorithm 1:
- [324, 7, 16, 11]
- [36, 0, 93, 27]
- Algorithm 2:
- [390, 4, 60, 70]
- [270, 11, 104, 28]
...
其中仍然有不需要的新文档语句。我需要在我的代码中更改什么才能使它们不显示?
你应该阅读 yaml 格式的文档。 您正在为每个项目创建一个地图,您想要的是这样的。
YAML::Emitter res;
res << YAML::BeginDoc << YAML::BeginMap;
for (int i = 0; i < 5; i++)
{
res << YAML::Key << i
<< YAML::Value << 42;
}
res << YAML::EndMap << YAML::EndDoc;
编辑...
你只需要按照你想要访问数据的方式编写 yaml,所以如果你这样做:
---
frame_0:
algorithm_1: 1
algorithm_2: 2
frame_1:
algorithm_1: 10
algorithm_2: 2
frame_2:
algorithm_1: 8
algorithm_2: 22
frame_3:
algorithm_1: 1
algorithm_2: 23
frame_4:
algorithm_1: 12
algorithm_2: 21
...
您可以通过以下方式访问 frame_3 中 algorithm_2 的值:
YAML::Node yaml = YAML::Load(res.c_str());
int value = yaml["frame_3"]["algorithm_2"].as<int>();
编辑...
YAML::Emitter res;
res << YAML::BeginDoc;
res << YAML::BeginMap;
for (int i = 3; i < 7; i++)
{
res << YAML::Key << i
<< YAML::Value
<< YAML::BeginSeq
<< YAML::BeginMap
<< YAML::Key << "Algorithm 1"
<< YAML::Value
<< YAML::BeginSeq
<< YAML::Flow
<< YAML::BeginSeq << 54 * i << 42 / i << 10 + i << 17 - i << YAML::EndSeq
<< YAML::Flow
<< YAML::BeginSeq << 6 * i << 3 / i << 87 + i << 33 - i << YAML::EndSeq
<< YAML::EndSeq
<< YAML::EndMap
<< YAML::BeginMap
<< YAML::Key << "Algorithm 2"
<< YAML::Value
<< YAML::BeginSeq
<< YAML::Flow
<< YAML::BeginSeq << 65 * i << 27 / i << 54 + i << 76 - i << YAML::EndSeq
<< YAML::Flow
<< YAML::BeginSeq << 45 * i << 66 / i << 98 + i << 34 - i << YAML::EndSeq
<< YAML::EndSeq
<< YAML::EndMap
<< YAML::EndSeq;
}
res << YAML::EndMap;
res << YAML::EndDoc;
这会做你想做的,你的问题是(假设你想要一个键从 3 到 7 的地图)你正在为 3、4、5、6 和 7 创建一个地图而不是一个地图使用键 3,4,...,7