有没有一种很好的方法可以将以下代码简化为使用C ++和可能的boost库的单行代码。我基本上有一个消息列表,其中title()作为成员函数。我想知道列表中是否存在具有给定标题的消息。
std::string title = "some title";
bool unique = true;
BOOST_FOREACH(Message& m, messages) {
if (m.title() == title) {
unique = false;
break;
}
}
如果您熟悉C#Linq,下面的C ++版本会很棒:
unique = (messages.FirstOrDefault(m => m.title() == title) == null);
不幸的是我不能使用C ++ 11,但是如果你有一个C ++ 11的例子,我很想看到它以供将来参考。
提前致谢。
答案 0 :(得分:2)
至少从外观上看,您可能希望使用std::map
来存储按标题键入的消息:
std::map<std::string, Message> messages;
...在这种情况下,您的搜索会变成:
bool unique = messages.find(title) == messages.end();
如果您坚持进行线性搜索并希望在title
成为Message
成员的情况下维持当前状态,则可以执行以下操作:
bool unique = std::find(messages.begin(), messages.end(),
[title](Message const &m) { return m.title == title; })
== messages.end();
但是,你可能不想做上述任何事情。相反,你可能只想使用std::set
或std::map
,而不是在添加之前搜索项目是否已经存在,只需使用insert,如果带有该键的项目将会失败已存在(但如果标题是新的,则添加)。由于我们已经考虑过使用std::map
,让我们考虑一下如何使用集合:
class Message {
std::string title;
// other stuff
public:
bool operator<(Message const &other) const { return title < other.title; }
}:
std::set<Message> messages;
messages.insert(some_new_message); // automatically unique
根据具体情况(如果您有很多消息,不关心它们的排序),您可能希望使用std::unordered_set
而不是std::set
(这同样适用于{{ 1}}与std::map
)。
答案 1 :(得分:1)
在使用boost的C ++中,您应该可以执行以下操作:
bool unique = boost::find_if(messages, boost::bind( &Message::title, _1 ) == title) == messages.end();
在C ++ 11中使用Linq和boost,你应该可以这样写:
bool unique = boost::empty(LINQ(from(m, message) where(m.title() == title)));
您不能在C ++中使用相同的first_or_default
,因为默认值不是空指针。