我想遍歷資料結構并收集元素的路徑。我想以一種對結構進行迭代的方式盡可能通用(請參閱 參考資料void WithAllMembersRecursively(..)),并將結構上的操作作為引數插入。
下面的代碼將回傳:
C
C::B
C::B::A
但目標是:
C
C::B
C::A
有沒有辦法設計 lambda 及其引數來達到預期的結果?
筆記:
- 是的,我知道連續堆疊的原因是由
string& fullPathlambda 引起的。因為它FullPath是通過參考傳遞的。 string fullPath另一方面,使用會導致另一個錯誤的結果,因為FullPath("") 是按值傳遞的,因此每個 lambda 呼叫只會看到空字串:
C
B
A
- 不能修改類和資料樹以插入附加資訊。
- 到目前為止,我為我的專案確定的當前次優解決方案具有遞回方法中從父級到子級的路徑的分配和傳遞。但這是我想擺脫的東西,以允許其他人結合他們的邏輯使用遞回方法:
template<typename F, typename... Args>
void WithAllMembersRecursively(MyElement* pElement, string parentPath, const F& f, Args&&... args)
{
string newPath = parentPath.empty() ? pElement->mName : parentPath "::" pElement->mName;
f(pDOInterface, newPath, std::forward<Args>(args)...);
for (auto pMember: pElement->mMembers)
{
WithAllMembersRecursively(pMember, newPath, f, std::forward<Args>(args)...);
}
}
代碼示例:
#include <iostream>
#include <vector>
using namespace std;
class MyElement
{
public:
MyElement(string name) : mName(name) {}
void AddElement(MyElement* elem) { mMembers.emplace_back(elem); }
string mName;
vector<MyElement*> mMembers;
};
template<typename F, typename... Args>
void WithAllMembersRecursively(MyElement * pElem, const F & f, Args&&... args)
{
f(pElem, args...);
for (auto pMember : pElem->mMembers)
{
WithAllMembersRecursively(pMember, f, std::forward<Args>(args)...);
}
}
int main()
{
MyElement C("C");
MyElement B("B");
MyElement A("A");
C.AddElement(&B);
C.AddElement(&A);
vector<string> AllPaths;
string FullPath = "";
WithAllMembersRecursively(&C, [&AllPaths](MyElement* elem, string& fullPath) {
fullPath = fullPath.empty() ? elem->mName : fullPath "::" elem->mName;
AllPaths.emplace_back(fullPath);
}, FullPath);
for (auto e : AllPaths)
{
cout << e << endl;
}
return 0;
}
uj5u.com熱心網友回復:
當遞回遍歷完全完成一個專案時,您需要某種方式從路徑中彈出一個專案。
當前呼叫f本質上是“預訪問”呼叫,然后訪問發生,這是遍歷所有子級并遞回訪問的主要遞回函式。如果您還添加了訪問后呼叫,您將有足夠的靈活性從運行狀態中彈出,而無需更改任何其他代碼。
一種方法是傳入另一個函子物件來執行彈出操作。以下將為您提供所需的輸出。
#include <iostream>
#include <vector>
using namespace std;
class MyElement
{
public:
MyElement(string name) : mName(name) {}
void AddElement(MyElement* elem) { mMembers.emplace_back(elem); }
string mName;
vector<MyElement*> mMembers;
};
template<typename C, typename F, typename... Args>
void WithAllMembersRecursively(MyElement* pElem, const C& post_visit, const F& pre_visit, Args&&... args)
{
pre_visit(pElem, args...);
for (auto pMember : pElem->mMembers) {
WithAllMembersRecursively(pMember, clear, f, std::forward<Args>(args)...);
}
post_visit();
}
int main()
{
MyElement mC("mC");
MyElement mCmB("mB");
MyElement mCmBmA("mA");
MyElement mCmBmRevA("mrevA");
MyElement mCmRevB("mRevB");
MyElement mCmRevBmA("mA");
MyElement mCmRevBmRevA("mrevA");
mCmRevB.AddElement(&mCmRevBmA);
mCmRevB.AddElement(&mCmRevBmRevA);
mCmB.AddElement(&mCmBmA);
mCmB.AddElement(&mCmBmRevA);
mC.AddElement(&mCmB);
mC.AddElement(&mCmRevB);
vector<string> AllPaths;
string FullPath = "";
WithAllMembersRecursively(&mC,
[&FullPath]() {
auto iter = FullPath.find_last_of("::");
if (iter == FullPath.size()) {
return;
}
FullPath = FullPath.substr(0, iter-1);
},
[&AllPaths](MyElement* elem, string& fullPath) {
fullPath = fullPath.empty() ? elem->mName : fullPath "::" elem->mName;
AllPaths.emplace_back(fullPath);
},
FullPath
);
for (auto e : AllPaths)
{
cout << e << endl;
}
return 0;
}
uj5u.com熱心網友回復:
我認為下面的代碼會做:
- 可變引數
args可以簡單地替換為const string& fullPath. f構建到 的完整路徑elem,將其添加到AllPaths并回傳它。WithAllMembersRecursively呼叫每個pMember傳遞完整路徑到pElem.
[演示]
#include <iostream> // cout
#include <string>
#include <vector>
class MyElement {
public:
MyElement(std::string name) : mName(name) {}
void AddElement(MyElement* elem) { mMembers.emplace_back(elem); }
std::string mName;
std::vector<MyElement*> mMembers;
};
template <typename F>
void WithAllMembersRecursively(MyElement* pElem, const F& f, const std::string& fullPath) {
auto newFullPath{ f(pElem, fullPath) }; // add to AllPaths and get path to current node
for (auto pMember : pElem->mMembers) {
WithAllMembersRecursively(pMember, f, newFullPath);
}
}
int main() {
MyElement mC("mC");
MyElement mCmB("mB");
MyElement mCmBmA("mA");
MyElement mCmBmRevA("mrevA");
MyElement mCmRevB("mrevB");
MyElement mCmRevBmA("mA");
MyElement mCmRevBmRevA("mrevA");
mCmRevB.AddElement(&mCmRevBmA);
mCmRevB.AddElement(&mCmRevBmRevA);
mCmB.AddElement(&mCmBmA);
mCmB.AddElement(&mCmBmRevA);
mC.AddElement(&mCmB);
mC.AddElement(&mCmRevB);
std::vector<std::string> AllPaths{};
std::string FullPath{};
WithAllMembersRecursively(
&mC,
[&AllPaths](MyElement* elem, const std::string& fullPath) {
std::string ret{fullPath.empty() ? elem->mName : fullPath "::" elem->mName};
AllPaths.emplace_back(ret);
return ret;
},
FullPath);
for (auto e : AllPaths) {
std::cout << e << "\n";
}
}
// Outputs:
//
// mC
// mC::mB
// mC::mB::mA
// mC::mB::mrevA
// mC::mrevB
// mC::mrevB::mA
// mC::mrevB::mrevA
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/442121.html
上一篇:PythonRecursiveenumerate(),具有起始值增量
下一篇:求和為n的最小完美平方數
