【问题标题】:How do I trim my vector with a specific member variable?如何使用特定的成员变量修剪我的向量?
【发布时间】:2020-05-08 01:06:50
【问题描述】:

我有一个由字符串标题、int 页数、流派组成的类 Book。
我制作了一些书籍对象,我想返回一本奇幻类型的书,它的页数也排名第二。这是我所做的:

std::vector<Book> sortPages(vector<Book> books){                          //sorts books in descending order
    sort(books.begin(), books.end(), [](const Book& lhs, const Book rhs){
        return lhs.getPages() > rhs.getPages();
    });

    return books;
}

int main(){

    Book book ("The Hunger Games ", 374, "Adventure fiction");
    Book book1 ("Game of Thrones", 694, "Fantasy");
    Book book2 ("Harry Potter and the Philosopher's Stone", 223, "Fantasy");
    Book book3 ("Holes", 272, "Adventure fiction");
    Book book4 ("The Hobbit", 400, "Fantasy");
    Book book5 ("The Maze Runner", 375, "Adventure fiction");

    std:vector<Book> books;
    books.push_back(book);
    books.push_back(book1);
    books.push_back(book2);
    books.push_back(book3);
    books.push_back(book4);
    books.push_back(book5);

    sortPages(books);

    //get all fantasy books, maybe into a new vector?
    //print 2nd element of fantasy books vector

return 0;
}

我在想,我要不要创建一个新的向量来存储所有的奇幻书籍?这是我想要的输出。

"The Hobbit", 400, "Fantasy"

【问题讨论】:

    标签: c++


    【解决方案1】:

    您可以使用std::partition 获取所有Fantasy 书籍:

    auto i = std::partition(books.begin(), books.end(), 
                            [](auto const &book) {
                               return book.genre == "Fantasy"; 
                           });
    

    然后用std::nth_element得到页数第二多的书:

    std::nth_element(books.begin(), books.begin() + 1, i,
                      [](auto const &book1, auto const &book2) {
                         return book1.pages > book2.pages; 
                     });
    

    现在books[1] 有了答案。

    【讨论】:

      【解决方案2】:

      这是您的情况的解决方案。注意不建议在vector使用指针中使用object。

      #include <iostream>
      #include <vector>
      #include <algorithm>
      
      class Book{
      
          public:
              Book(std::string title, int pages, std::string gender):
              m_title(title), 
              m_pages(pages), 
              m_gender(gender)
              {}
              std::string getTitle() const  { return m_title;}
              int         getPages() const { return m_pages;}
              std::string getGender() const { return m_gender;}
              private:
              std::string m_title;
              int m_pages;
              std::string m_gender;
      };
      std::vector<Book*> sortPages(std::vector<Book*> books){                          //sorts books in descending order
          std::sort(books.begin(), books.end(), [](const Book* lhs, const Book* rhs){
              return lhs->getPages() > rhs->getPages();
          });
      
          return books;
      }
      
      
      std::vector<Book*> getSpecificGender(std::vector<Book*> books, const std::string gender){                          //sorts books in descending order
          std::vector<Book*> result;
          for(auto it=books.begin();it!=books.end();it++)
          {
              if(gender == (*it)->getGender())
              {
                  result.push_back(*it);
              }
          }
          std::sort(result.begin(), result.end(), [](const Book* lhs, const Book* rhs){
              return lhs->getPages() > rhs->getPages();
          });
      
          return result;
      }
      
      Book* get2ndRankBook(std::vector<Book*> books, const std::string gender){                          //sorts books in descending order
          Book* first_rank_book=nullptr;
          Book* second_rank_book=nullptr;
          std::sort(books.begin(), books.end(), [](const Book* lhs, const Book* rhs){
              return lhs->getPages() > rhs->getPages();
          });
      
          for(auto it=books.begin();it!=books.end();it++)
          {
              if(gender != (*it)->getGender())
              {
                  continue;
              }
              if(!first_rank_book)
              {
                  first_rank_book = *it;
              }
      
              if(first_rank_book->getPages()>(*it)->getPages())
              {
                  second_rank_book=first_rank_book;
                  first_rank_book = *it;
              }
          }
      
          return second_rank_book;
      }
      int main(){
      
          Book* book = new Book ("The Hunger Games ", 374, "Adventure fiction");
          Book* book1 = new Book ("Game of Thrones", 694, "Fantasy");
          Book* book2 = new Book ("Harry Potter and the Philosopher's Stone", 223, "Fantasy");
          Book* book3 = new Book ("Holes", 272, "Adventure fiction");
          Book* book4 = new Book ("The Hobbit", 400, "Fantasy");
          Book* book5 = new Book ("The Maze Runner", 375, "Adventure fiction");
      
          std::vector<Book*> books;
          books.push_back(book);
          books.push_back(book1);
          books.push_back(book2);
          books.push_back(book3);
          books.push_back(book4);
          books.push_back(book5);
      
          sortPages(books);
      
          //get all fantasy books, maybe into a new vector?
          //print 2nd element of fantasy books vector
      
          auto fantasy = getSpecificGender(books, "Fantasy");
          for(auto it=fantasy.begin();it!=fantasy.end();it++)
          {
              std::cout<<(*it)->getTitle()<<", "<<(*it)->getPages()<<", "<<(*it)->getGender()<<std::endl;
          }
      
          std::cout<<"2nd Rank:"<<std::endl;
      
          Book* second_book = get2ndRankBook(books,"Fantasy");
          if(!second_book)
          {
              std::cout<<"There is no second rank book!"<<std::endl;
          }
          else
          {
              std::cout<<second_book->getTitle()<<", "<<second_book->getPages()<<", "<<second_book->getGender()<<std::endl;
          }
      delete book;
      delete book1;
      delete book2;
      delete book3;
      delete book4;
      delete book5;
      return 0;
      }
      

      测试结果:

      Game of Thrones, 694, Fantasy                                                                                                                                                      
      The Hobbit, 400, Fantasy                                                                                                                                                           
      Harry Potter and the Philosopher's Stone, 223, Fantasy                                                                                                                             
      2nd Rank:                                                                                                                                                                          
      The Hobbit, 400, Fantasy  
      

      【讨论】:

      • “不建议在向量中使用对象使用引用或指针”是不好的建议,完全不正确。在 C++ 中甚至不可能使用引用向量(必须是 reference_wrapper),并且指针向量仅在特定情况下才真正有用——但不是很好,因为它们不传达所有权(在现代 C++ 中,应该是 @987654323 @/shared_ptr 除非只观察状态)。值类型的向量并没有什么不好,而 r-value/move 语义使得移动包含值的向量变得很便宜。
      • 此外,这个解决方案存在内存泄漏,因为分配的Books 都不是deleted。
      猜你喜欢
      • 2014-12-13
      • 2021-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-18
      相关资源
      最近更新 更多