如何删除用户定义类的 std::vector 中的重复项?

问题描述 投票:0回答:1

我有一个文本编辑器列表,每当用户选择文件时就会在应用程序上呈现该列表。它工作得很好,但是当我开始删除列表中的元素以表示它们已被用户关闭并且不会再次呈现时,当我选择之前删除的相同文件以具有重复项时,问题就开始出现。因此,我尝试先对列表进行排序,然后在渲染之前使用 std::unique 来删除重复项。

这是我渲染文本编辑器的部分

if(!Opened_TextEditors.empty())
{   
   std::sort(Opened_TextEditors.begin(), Opened_TextEditors.end());
   auto last = std::unique(Opened_TextEditors.begin(), Opened_TextEditors.end());
   Opened_TextEditors.erase(last, Opened_TextEditors.end());

   auto it = Opened_TextEditors.begin();
   while(it != Opened_TextEditors.end())
   {   
        if(it->IsWindowVisible())
        {   
            it->Render();
            if(it->IsWindowFocused()){
                char buffer[255];
                selected_window_path = it->GetPath(); // determines which window is active or currently selected. For writing contents on status bar
                selected_editor_path = it->GetPath(); // This is to deterimine which window is focused or currently selected. For determining where to render the next selected window. This is to reduce reordering during rendering.
                auto cpos = it->GetCursorPosition();

                snprintf(buffer, sizeof(buffer), "Ln %d, Col %-6d %6d lines  | %s | %s | %s | %s ", cpos.mLine + 1, cpos.mColumn + 1, it->GetTotalLines(),
                        it->IsOverwrite() ? "Ovr" : "Ins",
                        it->CanUndo() ? "*" : " ",
                        it->GetFileExtension().c_str(), 
                        it->GetFileName().c_str()
                 );
                 current_editor = std::string(buffer);
            }
            ++it;
        }
        else {//Bug: When the editor was deleted and is selected again to be rendered, causes some sort of anomalies where it tends not being docked and somtimes when it was rendered and tried to close any window, every window will be deleted.
             it = Opened_TextEditors.erase(it);
             }
           }
        }

这是我添加所选文本编辑器的部分

auto it = std::find(Opened_TextEditors.begin(), Opened_TextEditors.end(), parentNode.FullPath);
if(it == Opened_TextEditors.end())
{   
     static unsigned int id = 0;
     ArmSimPro::TextEditor editor(parentNode.FullPath, id,bg_col.GetCol());
     auto programming_lang = ArmSimPro::TextEditor::LanguageDefinition::CPlusPlus();
     ++id;
     for (int i = 0; i < sizeof(ppnames) / sizeof(ppnames[0]); ++i)
           std::future<void> PreprocIdentifier = std::async(std::launch::async, SetupPreprocIdentifiers, programming_lang, ppvalues[i]);
     for (int i = 0; i < sizeof(identifiers) / sizeof(identifiers[0]); ++i)
            std::future<void> Identifiers = std::async(std::launch::async, SetupIdentifiers, programming_lang, identifiers[i], idecls[i]);
                
    editor.SetLanguageDefinition(programming_lang);

    std::ifstream t(parentNode.FullPath.c_str());
    if (t.good())
    {
        std::string str;
        t.seekg(0, std::ios::end);
        str.reserve(t.tellg());
        t.seekg(0, std::ios::beg);
        str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());

        editor.SetText(str);
     }

     if(!selected_editor_path.empty()){
         int index = GetTextEditorIndex(selected_editor_path) + 1;
         Opened_TextEditors.insert(Opened_TextEditors.begin() + index, editor);
     }
     if(Opened_TextEditors.empty())
         Opened_TextEditors.push_back(editor);
     }

当我运行它时,它给出了一条错误消息:

call to object of class type 'std::less<void>': no matching call operator found
call to object of class type 'std::less<void>': no matching call operator found 

因此,我在类上添加了一个重载“==”运算符的函数:

class TextEditor
{
 public:
        .....
        bool operator==(TextEditor& other) { return this->path == other.path; }
        bool operator==(const TextEditor& other) { return this->path == other.path; }
        bool operator==(const std::string& full_path) const { return this->path == full_path; }
        .....
};

我在

<algorithm>
方面没有太多经验,因为我刚刚开始学习几个月,但我怀疑错误来自于
std::unique
。我发现this类似的问题,但仍然遇到相同的错误。我可以在
TextEditor
类上添加任何内容来满足
std::unique
上的参数吗?

在这个问题上,我看到人们说使用

std::set
来避免重复。但是,要允许在当前选定的文本编辑器旁边添加文本编辑器,需要能够在特定索引处插入。这是通过搜索列表并找到具有指定文件路径的编辑器然后获取其位置来完成的。

c++ algorithm vector stl c++17
1个回答
0
投票

错误很可能来自

std::sort
而不是
std::unique
。 2-参数
std::sort
要求类型可以与
<
进行比较,而
TextEditor
不具备。

我会使用允许使用谓词的 3 参数

std::sort
,而不必向
operator <
类提供重载的
TextEditor

这是一个完整的示例:

#include <vector>
#include <iostream>
#include <algorithm>

class TextEditor
{
    std::string path;
    public:
        TextEditor(const char * p) : path(p) {}
        const std::string& getPath() const { return path;}
};

int main()
{
    std::vector<TextEditor> v;
    v.push_back("path1");
    v.push_back("path2");
    v.push_back("path1");  // Duplicate

    std::sort(v.begin(), v.end(), [](const TextEditor& e1, const TextEditor& e2)
    { return e1.getPath() < e2.getPath(); });

    auto it = std::unique(v.begin(), v.end(), [](const TextEditor& e1, const TextEditor& e2)
    { return e1.getPath() == e2.getPath(); });

    v.erase(it, v.end());

    for (auto& te : v)
    {
        std::cout << te.getPath() << "\n";
    }
}

输出:

path1
path2

请注意,进行了 3 参数

std::unique
调用,因此不需要编写重载的
operator==

© www.soinside.com 2019 - 2024. All rights reserved.