簡體   English   中英

c ++ 指向指針排序向量的指針向量

[英]c++ vector of pointers to vector of pointers ordering

我有兩個類,每個類都有一個指向Data的指針向量。 我想要做的是在類的矢量分配指針Sample2的指針在類的矢量Sample1 問題是,當我在第二個向量中分配指針時,它們存儲的順序是第一個向量的順序。 我想按插入順序存儲它們。

這是代碼的最小可重現示例

#include <iostream>
#include <vector>

using namespace std; //for sample purposes

// For simplicity, the data is just a string in this example.
using Data = string;
// In the real code there is a class with a certain vector as a member,
// but for this example we can reduce it to just the vector.
using Sample1 = vector<Data*>;

類 Sample2 — 問題就在這里

class Sample2 {
    vector<Data*> autodromos2;

public:
    vector<Data*>& getAutodromos() { return autodromos2; }

    // ** This is the function with the problem. **
    void addAutodromos2(vector<string>& arguments, vector<Data*>& autodromos)
    {
        for (Data* a : autodromos) {
            for (string &s : arguments) {
                if (s == *a) { // The real test is more complex.
                    getAutodromos().push_back(a);
                    break;
                }
            }
        }
    }
};

主要功能(生成數據並調用addAutodromos2

int main()
{
    // Create the list of elements to add to a `Sample2`.
    // Note that these are strings, not Data objects (in the real code).
    vector<string> arguments { "fourth", "first", "third" };

    // Create the `Sample1` data with which to work.
    Sample1 s1 {
        new Data("first"), new Data("second"), new Data("third"), 
        new Data("fourth"), new Data("fifth") 
    };

    // Create the `Sample2` data from the list and `s1`.
    Sample2 s2;
    s2.addAutodromos2(arguments, s1);

    // Diagnostic:
    for (Data* a : s2.getAutodromos()) {
        cout << *a << endl;
    }
}

輸出是

first 
third 
fourth

什么時候應該

fourth 
first 
third

實際上addAutodromos2()循環的序列問題您需要使用以下代碼更改函數:

    for (string s : arguments) 
    {
        for (Data* a : autodromos) 
        {            
            if (s == *a) { // The real test is more complex.
                getAutodromos().push_back(a);
                break;
            }
        }
    }

切換 for 循環。 輸出是fourth first third

希望這會有所幫助。

有一種觀點認為,如果在函數中嵌套了循環,那么您的思考可能不夠抽象。 雖然這有時可能有點誇大其詞,但在這種情況下它確實有價值。 讓我們看看內循環。

            for (string s : arguments) {
                if (s == *a) {
                    getAutodromos().push_back(a);
                    break;
                }
            }

此循環在arguments搜索*a ,如果找到則執行某些操作。 搜索是一個可以抽象成它自己的函數的概念,我們稱之為found ,一個返回bool的函數。

    // Preliminary revision
    void addAutodromos2(vector<string>& arguments, vector<Data*>& autodromos)
    {
        for (Data* a : autodromos) {
            if ( found(arguments, *a) ) {
                getAutodromos().push_back(a);
            }
        }
    }

只看一個循環,應該更清楚問題是什么。 元素被添加到getAutodromos()在它們出現的順序autodromos 要使用arguments的順序,您需要遍歷它。 (我將幫助函數的名稱更改為find_by_name並讓它返回一個迭代器到找到的元素或結束迭代器。布爾返回值不再足夠。)

    // Final revision
    void addAutodromos2(vector<string>& arguments, vector<Data*>& autodromos)
    {
        for (string s : arguments) {
            auto result = find_by_name(autodromos, s);
            if ( result != autodromos.end() ) {
                getAutodromos().push_back(*result);
            }
        }
    }

這里缺少的部分是find_by_name函數。 好消息是這個任務非常常見,功能是標准庫的一部分,在頭文件<algorithm> 壞消息是使用庫函數需要輸入一些類型,因為參數更復雜(以獲得更大的靈活性)。 您可能想要定義一個包裝器來專門針對您的情況。

// Returns an iterator to the element with the indicated name, or
// autodromos.end() if not found.
static auto find_by_name(const vector<Data*> & autodromos, const string & name)
{
    return std::find_if(autodromos.begin(), autodromos.end(), [&name](Data *a){
        return name == *a; // or name == a->get_name(), when Data is more complex
    });
}

請注意,如果真正的測試就像比較name == *a一樣簡單,那么可以使用std::find代替std::find_if ,並且不需要使用 lambda。 不要忘記在文件前面#include <algorithm>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM