【问题标题】:Find the largest / smallest key in a multimap of pairs <Class object, enum>, using multimap algorithms (std::minmax_element)?使用多映射算法 (std::minmax_element) 在对 <Class object, enum> 的多映射中查找最大/最小键?
【发布时间】:2016-02-09 20:25:09
【问题描述】:

我有这个程序,我将成对的类对象 + 枚举放在一个多映射中。类对象有一个成员类型 int 文件大小。我想在我的多重映射中找到最大和最小的键。

我通过创建 3 个迭代器来做到这一点,将每个对象与下一个对象进行比较,如果它更小(或更大,取决于我搜索的内容),它将被分配给第三个迭代器。之后,我只打印出第三个迭代器。有没有其他优雅的方式来做到这一点?我知道这行得通,但我确信还有另一种方法 - 我似乎找不到它。

这是我的最大文件功能:

void getMaxFile() {
        multimap<CFile, Filetype>::iterator p = m_DirectoryMap.begin();
        multimap<CFile, Filetype>::iterator t = m_DirectoryMap.begin();
        multimap<CFile, Filetype>::iterator x = m_DirectoryMap.begin();
        t++;
        while  (p != m_DirectoryMap.end()) {
                if (p->first.getFileSize() > t->first.getFileSize())
                    x = p;
                ++p, ++t;
        }
        cout << "The largest file is: " << endl << x->first.getFileName()
             << '\t' << x->first.getFileSize() << '\t' << x->second << endl;
    }

第二个类的构造函数,我在其中制作多映射并用另一对类对象 + 枚举(从文件中读取)填充它:

 CDirectory (string n) {
              fp.open (n, ios::in);
              string dirName, fileName,  fType;
              int fileSize;
              fp >> dirName;
              m_strDirectory = dirName;
              while (fp >> fileName >> fileSize >> fType) {
                      CFile obj (fileName, fileSize);
                       if (fType == "Archive")
                  filetype = Filetype::Archive;
              else if (fType == "Hidden")
                  filetype = Filetype::Hidden;
              else if (fType == "ReadOnly")
                  filetype = Filetype::ReadOnly;
              else if (fType == "System")
                  filetype = Filetype::System;
              else
                  filetype = Filetype::FileNotSupported;
              m_DirectoryMap.insert(pair<CFile, Filetype>(CFile(obj.getFileName(), obj.getFileSize()), Filetype(filetype)));
              }
              multimap<CFile, Filetype>::iterator p = m_DirectoryMap.begin();
              while ( p != m_DirectoryMap.end()) {
                cout << endl << p->first.getFileName() << '\t' << p->first.getFileSize() << '\t' << p->second << endl;
                ++p;
              }
    }   

还有第一类(哪些对象是我的多重地图中的关键):

class CFile {
    string m_strFile;
    unsigned int m_size;
public:
    CFile () { m_strFile = ""; m_size = 0; }
    CFile (string name, int size ) { m_strFile = name; m_size = size; }
    string getFileName () const { return m_strFile; }
    int getFileSize () const { return m_size; }
    void setFileSize ( int size ) { m_size = size; }
    bool operator< (CFile& obj) {
        return ( m_size < obj.m_size );
    }
    bool operator== (const CFile& obj) {
        return ( m_size == obj.m_size );
    }
    friend ostream& operator<< ( ostream& ost, const CFile& obj ) {
        return ost << obj.m_strFile << obj.m_size;
    }
    friend istream& operator>> ( istream& ist, CFile& obj ) {
        return ist >> obj.m_strFile >> obj.m_size;
    }
    static bool Greater(const CFile& obj1, const CFile& obj2) {
        if ( obj1.m_size > obj2.m_size )
            return true;
        else
            return false;
    }
};

【问题讨论】:

  • 也许我没有得到它,但是由于地图是按键排序的,*being()*rbegin() 最小的就是最大的键吗?
  • 地图按键文件名(不是文件大小)排序。
  • 你是怎么做到的?我在这里看到的一切都让我相信它会按文件大小排序。地图是如何声明的?
  • 我有一个全局声明的bool operator&lt; (CFile obj1, CFile obj2) { return obj1.getFileName()&lt;obj2.getFileName(); },它按文件名对配对进行排序。

标签: c++ algorithm dictionary multimap


【解决方案1】:

std::minmax_element 允许您传递比较器以在查看对象时使用,因此您可以执行以下操作:

auto p = std::minmax_element(m_directoryMap.begin(), m_directoryMap.end(), 
    [](CFile const &a, CFile const &b) { return a.getFileSize() < b.getFileSize(); });

p 将成为您集合中的一对迭代器,因此您可以(例如)将它们打印出来:

std::cout << "Smallest: " << p.first->getFileSize() << " bytes\n";
std::cout << "Largest:  " << p.second->getFileSize() << " bytes\n";

然而,仔细观察,您似乎仍然在使用 size 成员作为文件的排序。既然如此,您可以使用地图已经根据您关心的数据排序的事实,因此您可以使用:

std::cout << "Smallest: " << m_directoryMap.begin()->getFileSize() << " bytes\n";
std::cout << "Largest:  " << m_directoryMap.rbegin()->getFileSize() << " bytes\n";

但是,如果仔细查看您的代码,您可能会遇到一些其他问题,这些问题可能会影响您在此处尝试执行的操作。这是您的代码的稍微简化(和重写)的版本,以及一些用于查找最小值和最大值(并打印出来)的代码:

#include <string>
#include <iostream>
#include <map>
#include <algorithm>

using std::string;
using std::istream;
using std::ostream;

class CFile {
    string m_strFile;
    unsigned int m_size;
public:
    CFile() { m_strFile = ""; m_size = 0; }
    CFile(string name, int size) { m_strFile = name; m_size = size; }
    string getFileName() const { return m_strFile; }
    int getFileSize() const { return m_size; }
    void setFileSize(int size) { m_size = size; }
    bool operator< (CFile const& obj) const {
        return (m_size < obj.m_size);
    }
    bool operator== (const CFile& obj) const {
        return (m_size == obj.m_size);
    }
    friend ostream& operator<< (ostream& ost, const CFile& obj) {
        return ost << obj.m_strFile << obj.m_size;
    }
    friend istream& operator>> (istream& ist, CFile& obj) {
        return ist >> obj.m_strFile >> obj.m_size;
    }
    static bool Greater(const CFile& obj1, const CFile& obj2) {
        return (obj1.m_size > obj2.m_size);
    }
};

struct cmp {
    bool operator()(CFile const &a, CFile const &b) {
        return a.getFileName() < b.getFileName();
    }
};

int main() {
    std::multimap<CFile, int, cmp> files {
        { CFile { "abc", 123 }, 1 },
        { CFile { "cde", 234 }, 2 },
        { CFile { "def", 345 }, 3 }
    };

    auto p = std::minmax_element(files.begin(), files.end(),
        [](auto const &a, auto const &b) { return a.first.getFileSize() < b.first.getFileSize(); });

    std::cout << p.first->first.getFileSize() << "\n";
    std::cout << p.second->first.getFileSize() << "\n";
}

【讨论】:

  • std::multimap 中没有 frontback。不过你可以使用*being()*rbegin()
  • @hopittyhop: 哦,是的,对不起——你的比较函数会传递一个std::pair&lt;CFile, CDirectory::Filetype&gt;,所以你需要a.first.getFileSize() &lt; b.first.getFileSize();
  • @hopittyhop:我们似乎在绕圈子。首先你说pair&lt;...&gt; 没有成员getFileSize(这是真的——只有成员firstsecond)。如果你得到一个pair&lt;x, Y&gt;,那么first成员就是X,所以要调用X的成员函数,你需要调用a.first.member()。另一方面,如果您实际上是直接收到X(而不是作为pair 的成员),那么您只需调用a.member
  • @Jerry Coffin:我完全理解并遵循您的逻辑,但不知何故,我无法让它工作。语法不起作用。
  • @Jerry Coffin:这是我整个程序的链接,如果你有时间并且愿意在某个时候查看它 - pastebin.com/2d5Ta9Q2
猜你喜欢
  • 1970-01-01
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多