【问题标题】:Custom Ordering in Set String Elements集合字符串元素中的自定义排序
【发布时间】:2021-01-29 12:04:36
【问题描述】:

std::set<std::string> &uniq_email_list;

我有一组许多电子邮件元素,例如:

('foo@bar.com', 'foo2@bar.com', 'foo@bazz.com', 'foo2@bazz.com','zfoo@bar.com')

然后我将这些元素写入文件

for(iter = uniq_email_list.begin() ; iter!=uniq_email_list.end(); ++iter){  
            output_file<< *iter << std::endl;
        }

在我将这些元素写入文件之前,我想按'@'下一个域名排序 我希望它在文件中看起来像这样

foo@bar.com
foo2@bar.com
zfoo@bar.com
foo@bazz.com
foo2@bazz.com

我知道

您不能使用集合,它的排序方式是特定集合类型的一部分。给定的集合具有固定的集合顺序,无法更改。

您可以相对轻松地创建具有相同数据的新集合。只需创建一个根据新标准进行排序的新集合

我看了那篇帖子Sorting Sets using std::sort 但我找不到问题的答案。

根据我的研究,我发现了类似的东西

std::set<string>::iterator &it;
it=myset.find('@');

我可以用这种结构对返回的地址进行排序吗?或者如果有其他适合这个问题的解决方案,提前谢谢你,我准备就C++解决方案相关的问题获得建议。

【问题讨论】:

  • 请不要使用“C/C++”。 C 和 C++ 是非常不同的语言。你显示的显然不是 C。
  • “这个结构”是什么意思?不,std::set 无法排序,无论代码中存在什么其他结构。
  • 您可以将自定义比较器设置为std::setstd::set<Key,Compare,Allocator>::set - cppreference.com

标签: c++ sorting set


【解决方案1】:

如果您要单独使用域和名称部分,我建议您将它们拆分并放入 email 类中,您为其提供满足创建所需的 Compare 要求的 operator&lt;一个std::set&lt;email&gt;

#include <tuple>  // std::tie

struct email {
    std::string name;
    std::string domain;

    // The compare operator used by default by a std::set<email>:
    bool operator<(const email& rhs) const {

        // using std::tie makes creating an operator< that does
        // strict weak ordering relatively easy:

        return std::tie(domain, name) < std::tie(rhs.domain, rhs.name);
    }
};

std::ostream& operator<<(std::ostream& os, const email& e) {
    os << e.name;
    if(not e.domain.empty()) os << '@' << e.domain;
    return os;
}

std::istream& operator>>(std::istream& is, email& e) {
    if(std::string tmp; is >> tmp) {

        auto at_pos = tmp.find('@');        
        e.name = tmp.substr(0, at_pos);

        if(at_pos != std::string::npos) {    
            e.domain = tmp.substr(at_pos + 1);
        } else {
            e.domain.clear();
        }
    }
    return is;
}

您现在可以将它们放入 std::set&lt;email&gt;std::vector&lt;email&gt;(以及 std::sort 那个向量)中,然后按照成员 operator&lt; 指定的顺序将它们流式传输出去。域在前,名称在后,还从流中读取:

email tmp;
while(instream >> tmp) {
    std::cout << "read address: " << tmp << '\n';
}

Demo

【讨论】:

    【解决方案2】:
    class EmailCompare
    {
    public:
        bool operator()(const std::string& a, const std::string& b) const {
            // your code here
            return ... ;
        }
    };
    
    using EmailSet = std::set<std::string, EmailCompare>;
    

    【讨论】:

    • fwiw,我回答了同样的问题,但现在才意识到使用仅比较 @ 之后的部分的自定义比较器,在集合中不能有 foo2@bar.comzfoo@bar.com同时。也许有一个我看不到的明显解决方案......
    • // your code here 不仅要比较主机,还要比较用户。
    • 是的,有道理,而不是比较 foo2@bar.comzfoo@bar.com 比较 @bar.comfoo2@bar.comzfoo
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2011-08-08
    • 2015-09-22
    相关资源
    最近更新 更多