如何使用特定的成员变量修剪我的向量?

Posted

技术标签:

【中文标题】如何使用特定的成员变量修剪我的向量?【英文标题】: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"

【问题讨论】:

【参考方案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。

以上是关于如何使用特定的成员变量修剪我的向量?的主要内容,如果未能解决你的问题,请参考以下文章

如何检测类中是不是存在特定的成员变量?

修剪字符串向量

如何修剪向量字符数组或字符串?

如何找到特定成员具有特定值的第一个结构?

如何制作特定类的成员函数或变量的别名(如 STL 容器)

如何使用 AVFoundation 修剪视频