使用集合存储自定义类,只有第一个插入有效

Posted

技术标签:

【中文标题】使用集合存储自定义类,只有第一个插入有效【英文标题】:Using a set to store a custom class, only the first insert works 【发布时间】:2014-08-02 22:02:10 【问题描述】:

基本问题 请阅读此问题,即使您没有时间查看所有其他详细信息。 :) - 我需要将我的自定义类(元组)的多个对象存储到一个集合中。该类仅包含一个字符串向量。 (根据项目要求)。我如何实现这一点,以便它唯一地识别每个元素(因此只消除相同的向量)? 2 - 我的教授建议我可以从自定义类(元组)中的向量字符串继承,这样我就不必编写自己的“运算符

1 - 这是真的吗? 2 - 如果没有,我是否可以使用继承来获得此功能?

更多细节,如果你有时间:)

我在网上看了一会儿,还没有找到解决问题的方法。首先,我承认这是一项学校作业(一个简单的关系数据库),所以我有一些要求要遵循(即使我现在不明白为什么要这样做)。

必修课

--> “关系” ------> 必须使用 std::set 来保存元组

-->“元组” ------> 是“属性值”的列表

我在课堂上得到提示,如果我扩展字符串向量,我不会在“元组”类中编写自己的运算符

问题: 我需要存储一组“元组”我要创建的类。我现在遇到的问题是只存储了第一个“元组”。我在集合旁边使用了一个向量,这样我就可以查看我的代码是否正在尝试做我想做的事情,看起来我的问题是集合正在识别我插入的每个“元组”等同于已经存在的“元组” ,因此我最终得到了一组只有 1 个“元组”,即使我应该有更多。

我在下面包含了我认为相关的代码。为了不让你看太多东西,在底部我展示了将新的“元组”插入到已经存在的“关系”中的函数,如果你查看 Relation 类,你会看到函数“insertTuple(Tuple tupIn);"它接收一个元组并将其添加到相关集合中。

我需要知道什么?

为什么集合中只存储一个项目? 如何解决此问题,以便所有非重复项目都存储在集合中? (假设我并不是所有的插入都是重复的,因为它们不是)。

感谢 ***,你们是一群聪明、有耐心的人!

元组.h

 #include <iostream>
 #include <vector>
 #include "DatalogProgram.h"
 using namespace std;


 class Tuple : public vector<string>
 
 private:
     vector<string> attributevals;
 public:
     Tuple();
     Tuple(Predicate input);
     ~Tuple();
     vector<string> returnAttributeVals();
     string toString();
 ;

元组.cpp

 #include "Tuple.h"
 Tuple :: Tuple()
 

 
 Tuple :: Tuple(Predicate input)
 
     // Here I will populate the tuple!
     attributevals.clear();
     for(int x = 0; x < input.returnParams().size(); x++)
     
         //cout << "Adding value to Tuple: " << endl;
         //cout << input.returnParams().at(x).toString() << endl;
         attributevals.push_back(input.returnParams().at(x).toString());
     
 
 Tuple :: ~Tuple()
 
     attributevals.clear();
 
 vector<string> Tuple :: returnAttributeVals()
 
     return attributevals;
 

 string Tuple :: toString()
 
     string value = "";
     for(int x = 0 ; x < attributevals.size() ; x++)
     
         value = value + attributevals.at(x) + " -|- ";
     
     return "Attribute Values : \n" + value;
 

关系.h

 #include <iostream>
 #include <set>
 #include <vector>
 #include <string>
 #include "Scheme.h"
 #include "Tuple.h"
 //#include "DatalogProgram.h"
 #pragma once
 using namespace std;

 class Relation
 
 private:
     string Rname;
     Scheme Rscheme;
     set<Tuple> Rtuples;
     vector<Tuple> RtempVec;
 public:
     Relation(string nameIn, Scheme schemeIn);
     Relation(string nameIn, Scheme schemeIn, set<Tuple> tuplesIn);
     ~Relation();
     void insertTuple(Tuple tupIn);
     void select();
     void project();
     void rename();
     void testOutput();
     string returnName();
     Scheme returnScheme();
     set<Tuple> returnTuples();
     string toString();
 ;

关系.cpp #include "Relation.h"

 Relation :: Relation(string nameIn, Scheme schemeIn)
 
     Rname = nameIn;
     Rscheme = schemeIn;
 
 Relation :: Relation(string nameIn, Scheme schemeIn, set<Tuple> tuplesIn)
 
     Rname = nameIn;
     Rscheme = schemeIn;
     Rtuples = tuplesIn;
 
 Relation :: ~Relation()
 
     Rname.clear();
     Rscheme.clear();
     Rtuples.clear();
 
 void Relation :: insertTuple(Tuple tupIn)
 
     cout << Rname << "  ->  Inserting the following Tuple :  \n" << tupIn.toString() << endl;
     Tuple temp = tupIn;
     Rtuples.insert(temp);
     cout << "Current # of tuples in this relation" << Rtuples.size() << endl;
     RtempVec.push_back(temp);
 
 string Relation :: returnName()
 
     return Rname;
 
 Scheme Relation :: returnScheme()
 
     return Rscheme;
 
 set<Tuple> Relation :: returnTuples()
 
     return Rtuples;
 
 string Relation :: toString()
 
cout << "Printing Relation " + Rname << endl;
cout << "Number of Tuples: " << Rtuples.size() << endl;
cout << "Number of tuples in temp Vector" << RtempVec.size() << endl;
set<Tuple> temp = Rtuples;
string result = "";
result = Rname + "\n" + Rscheme.toString() + "\n";
std::set<Tuple>::iterator setiter;
for(setiter = Rtuples.begin(); setiter!=Rtuples.end();setiter++)

    cout << "looping through tuples" << endl;
    Tuple temp = *setiter;
    result = result + " " + temp.toString() + "'\n";


return result;
 
 void select();
 void project();
 void rename();
 void testOutput();

现在我已经包含了比任何人都想看的更多的代码,但这里是创建我试图插入到关系中的元组的函数(进入集合)。

 void Database :: ProcessFacts(vector<Predicate> input)
 
     // So for facts I need to match the ID, then add the Paramaters to the tuple in the relation.
     // this means I itterate through the Relations already present, if it maches then I add a tuple!
     for (int x = 0; x < Drelations.size(); x++)
     
         for(int y = 0; y < input.size() ; y++)
         
             if(input.at(y).returnID() == Drelations.at(x).returnName())
             
                 cout << "adding a tuple to  -->  " << Drelations.at(x).returnName() << endl;
                 cout << "Tuple is: " << Tuple(input.at(y)).toString() << endl;
                 Drelations.at(x).insertTuple(Tuple(input.at(y)));
             
         
     
 

【问题讨论】:

你可能想在这里发布更少的代码,如果需要的话,把它放在像liveworkspace这样的网站上。此外,在调查您不理解的问题时,尤其是与他人分享时,请尝试生成minimal case。祝你好运;) @Antoine 可以!谢谢。 看起来你从向量继承,但实际上并没有在继承的向量中存储任何东西,你没有覆盖operator&lt;,所以你所有的元组都被比较为空向量,它们都是相同的.根据您的编辑,如果鼓励您从 vector 继承,这通常是一个坏主意,您应该删除 attributevals 并将字符串存储在您继承的对象中,所以只需 push_back(...) @RetiredNinja 迄今为止最有用的输入!我将如何实现这一点,以便将我的信息存储在继承的向量中,从而继承正确的 operator 目前您的元组有 2 个向量:一个是继承的,一个在 attributevals 字段中。您存储在字段中,但 【参考方案1】:

问题是您从向量继承以避免编写自己的运算符

从标准容器继承是可行的,但这并不总是最好的主意,因为它们没有虚拟析构函数。对于这个作业应该没问题,但你应该做一些研究,以便了解未来的问题。

这是一个示例,它演示了您当前代码的问题,并显示了使用继承和成员向量的两个替代方案。我推荐成员向量,因为它避免了从标准容器继承的问题,并且 operator

#include <cstdlib>
#include <iostream>
#include <set>
#include <string>
#include <vector>

class ProblemTuple : public std::vector<std::string>

public:
    void AddAttribute(const std::string& item)
    
        attributes.push_back(item);
    

    void Print() const
    
        for(const std::string& a : attributes)
        
            std::cout << a << " ";
        
        std::cout << "\n";
    
private:
    std::vector<std::string> attributes;
;

class InheritedTuple : public std::vector<std::string>

public:
    void AddAttribute(const std::string& item)
    
        push_back(item);
    

    void Print() const
    
        for(const std::string& a : *this)
        
            std::cout << a << " ";
        
        std::cout << "\n";
    
;

class CompositeTuple

public:
    void AddAttribute(const std::string& item)
    
        attributes.push_back(item);
    

    void Print() const
    
        for(const std::string& a : attributes)
        
            std::cout << a << " ";
        
        std::cout << "\n";
    

    bool operator<(const CompositeTuple& rhs) const
    
        return attributes < rhs.attributes;
    

private:
    std::vector<std::string> attributes;
;

std::string randomString()

    std::string ret;
    for(int i = 0; i < 3; ++i)
    
        ret += 'a' + (std::rand() % 26);
    
    return ret;


template<typename T>
void PrintSet(const std::string& title, const std::set<T>& set)

    std::cout << title << "\n";
    for(const auto& s : set)
    
        std::cout << "   ";
        s.Print();
    


int main()

    //Not calling srand on purpose so the result should be the same every time.
    std::set<ProblemTuple> ProblemSet;
    std::set<InheritedTuple> InheritedSet;
    std::set<CompositeTuple> CompositeSet;

    for(int i = 0; i < 3; ++i)
    
        ProblemTuple pt;
        InheritedTuple it;
        CompositeTuple ct;
        for(int j = 0; j < 3; ++j)
        
            std::string s(randomString());
            pt.AddAttribute(s);
            it.AddAttribute(s);
            ct.AddAttribute(s);
        
        ProblemSet.insert(pt);
        InheritedSet.insert(it);
        CompositeSet.insert(ct);
    

    PrintSet("Problem", ProblemSet);
    PrintSet("Inherited", InheritedSet);
    PrintSet("Composite", CompositeSet);

    return 0;

【讨论】:

很好的帮助!感谢您花时间解释这一点,希望这不仅对我有用,而且对其他对继承缺乏类似理解的人有用。

以上是关于使用集合存储自定义类,只有第一个插入有效的主要内容,如果未能解决你的问题,请参考以下文章

自定义的Node类和集合类linkedList<Item>的区别?

Swift-自定义 UITableViewCell 委托给 UIViewController 只有一个协议有效

Java基础语法(自定义类ArrayList集合)

hashmap的嵌套,存储一个自定义类

自定义 FieldSetMapper 中忽略的自动装配 JpaRepository 保存

为自定义类保存到 nsuserdefaults 的最佳方法?