2016-02-08 8 views
1

Есть ли способ, которым вы могли бы использовать алгоритмы map.find()/map.count() для ключа, который является типа объекта класса?Использование map.find() и count() для ключа, который является типом объекта класса

My multimap состоит из пар - map.<myClass, enum> и у myClass есть член, например, имя файла. Я хотел бы искать дубликаты имен файлов на моей карте, и я прочитал, что функции find() и count() выполняют это для ключей, но можно реализовать их для поиска члена ключа?

Вот код:

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

Это конструктор второго класса, который имеет Multimap пара (объекты другого класса, перечисление>).

А вот первый класс:

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

Я хочу найти дубликаты string m_strFile;

+0

Это будет лучше, если вы может опубликовать некоторый код, предпочтительно [Минимальный, Полный и Подтверждаемый пример] (http://stackoverflow.com/help/mcve). –

+0

Что вы хотите, так это std :: find_if (http://www.cplusplus.com/reference/algorithm/find_if/) – kfsone

+0

См. Мой комментарий к ответу Ричарда Ходжа относительно перегрузки вашего оператора. Что касается использования одного сравнения для хранения на карте или в поиске карты ... вы не можете выполнять поиск с помощью функции поиска карты, потому что эта функция использует поиск двоичного дерева. Вам нужно использовать find_if, который будет линейно перемещаться по дереву, чтобы найти объект. –

ответ

3

A std::multimap сравнивает ключи через Predicate (объект функции, оператор вызова которого ссылается на два объекта типа Key).

Предикат по умолчанию для std::multimap: std::less<>, поэтому карты обычно упорядочиваются по возрастающей клавише.

Для того, чтобы ваши ключи были сопоставимы, вам нужно либо указать собственный предикат в списке аргументов шаблона карты (в третьей позиции), либо дать вашему классу оператор <.

Тогда вы бы перебирать карты в группах пар, таких как:

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

для полноты картины, вот еще один способ устранения дубликатов без использования 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() && ifind->first == to_erase ;) 
    { 
    // NOTE: take a copy of the advanced iterator BEFORE erasing 
    // the iterator. 
    auto inext = std::next(ifind); 
    mmap.erase(ifind); 
    ifind = inext; 
    } 
} 
+0

Пожалуйста, не переопределяйте операторы равенства, чтобы делать что-либо, кроме сравнения полного, наблюдаемого состояния ваших объектов. Он полностью поддерживает шланги. Вместо этого используйте предикатную функцию карты. –

+0

@CrazyEddie Согласен. Я ленился. Исправлена. –