hopittyhop February 2016

Using map.find() and count() on a key, which is a class object type

Is there any way that you could possible use map.find() / map.count() algorithms for a key, which is of type object of a class?

My multimap is made of pairs - map.<myClass, enum> and myClass has some member, like Filename for example. I would like to search for duplicate Filenames in my map and I have read that find() and count() functions do that for keys, but is possible to implement them to search for a member of the key?

Here is some code:

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;
              }
    }

This is the constructor of the second class, which has a multimap of pairs (Objects of another class, enum>).

And here is the first class:

class CFile {
    string m_        

Answers


Richard Hodges February 2016

A std::multimap compares keys through a Predicate (a function object whose call operator takes a reference to two objects of type Key).

The default predicate for a std::multimap is std::less<>, which is why maps are normally ordered by ascending key.

In order to make your keys comparable, you either need to specify a custom predicate in the map's template argument list (in the third position), or give your class a < operator.

Then you would iterate through the map in groups of pairs, such as:

struct MyKey
{
    MyKey(std::string fname) : _filename { std::move(fname) } {}
    const std::string& filename() const { return _filename; }

    private:
      std::string _filename;
};

// define a predicate to order the map
struct order_by_filename {
  bool operator()(const MyKey& l, const MyKey& r) const {
    return l.filename() < r.filename();
  }
};

struct DataObject {};

std::multimap<MyKey, DataObject, order_by_filename> my_map;

void strip_duplicates()
{
    for(auto current = my_map.begin() ; current != my_map.end() ; )
    {
        auto range = my_map.equal_range(current->first);
        // range is a std::pair containing the first and last iterator
        // of the range with equal keys
        auto num_items = range.second - range.first;
        if (num_items > 1) {
            // strip duplicates
            my_map.erase(std::next(range.first), range.second);
        }
        // move to next range of keys
        current = range.second;
    }
}

for completeness, here's another way eliminating duplicates without using equal_range:

void erase_all_but_one(std::multimap<Key, Value>& mmap, const Key& to_erase)
{
  auto ifind = mmap.find(to_erase);
  if (ifind == mmap.end()) return;
  for(ifind = std::next(ifind) ; ifind != mmap.end() && ifin 

Post Status

Asked in February 2016
Viewed 3,900 times
Voted 12
Answered 1 times

Search




Leave an answer