所以你有一个集合,你想看看它中没有任何项目通过测试。如果任何通过测试很容易,并且看起来像这样:
for (int i = 0; i < collectionSize; i++)
{
if(ItemPasses(collection[i]))
{
// do code for if any pass
break;
}
}
但要做相反的事情,如果没有通过测试,我无法想到一个真正巧妙的方法来做到这一点,以下是我能提出的方法:
// nice to look at but uses an unecessary variable 'anItemPassed'
bool anItemPassed = false;
for (int i = 0; i < collectionSize; i++)
{
if(ItemPasses(collection[i]))
{
anItemPassed = true;
break;
}
}
if (!anItemPassed)
{
//...
}
//---------------------------------------------------------------------------------
// as efficient as possible but uses gotos.. nobody likes gotos.. lable stuff really isnt that neat.
for (int i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
goto ItemPassed;
}
}
//...
ItemPassed: { }
//-------------------------------------------------------------------------
// as efficient as possible and doesnt use the rarely used (and usually poorly supported in IDEs) goto/lable stuff, but doesnt use any nice loop construct, does it all manually
int i = 0;
for (; ; )
{
if (i >= collectionSize)
{
//...
break;
}
if (ItemPasses(collection[i]))
{
break;
}
i++;
}
我真的不喜欢其中任何一个,我一直想知道为什么从来没有像这样的结构:
for (int i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
break;
}
}
finally //executed if the loop terminates normally, not via breaks.
{
//...
}
所以简而言之,我的问题是:如果没有“收集”测试,是否有真正干净的方法?如果没有,是否有理由说上述内容不是一个好的语言特色?
编辑: 我立刻后悔在标签中加入c ++。我知道有很好的功能可以做到这一点,但假设升级库或诸如此类,也是用c / c ++编写的,大概是他们遇到了同样的问题。即使这些函数内置于该语言中,在这种情况下,“只是调用此函数”并不是我所寻找的答案。
所以也许我会专注于我的问题的最后一部分:有没有理由说上面的内容不是一个好的语言功能? 在我看来没有它就像没有'else'关键字与'if'
一起使用答案 0 :(得分:5)
对于C ++来说,它非常简单(C ++ 11 with none_of,C ++ 14 with auto lambda)
bool noneExist = std::none_of(std::begin(collection), std::end(collection), [](auto &item){
return item.matchesCondition(); // any evaluation can go here, or you could just supply an existing functor instead of a lambda
});
我在这里分配给一个bool,但你可以轻松地将它包装在if语句中(这假设一个名为MatchCondition的现有函数或函子对象,一个lambda可以工作,但在if中读取很多东西)条件):
if(std::none_of(std::begin(collection), std::end(collection), MatchCondition)){
//run your "if none of the above matched" code here.
}
旧的C ++ 98完成方法:
if(std::find_if(collection.begin(), collection.end(), MatchCondition) == collection.end()){
//run your "if none of the above matched" code here.
}
答案 1 :(得分:4)
“真正整洁”听起来有点基于意见,但这里有几个选择:
#include <iostream>
#include <algorithm>
#include <vector>
bool itemPasses(int i) {
return i > 10;
}
void printIfNonePass1(const std::vector<int>& collection) {
if (std::none_of(collection.cbegin(), collection.cend(), itemPasses))
std::cout << "None pass\n";
}
void printIfNonePass2(const std::vector<int>& collection) {
auto iter = collection.cbegin();
for(; iter != collection.cend(); ++iter) {
if (itemPasses(*iter))
break;
}
if (iter == collection.cend())
std::cout << "None pass\n";
}
void printIfNonePass3(const std::vector<int>& collection) {
size_t i = 0;
for(; i != collection.size(); ++i) {
if (itemPasses(collection[i]))
break;
}
if (i == collection.size())
std::cout << "None pass\n";
}
bool checkIfNonePass(const std::vector<int>& collection) {
for(int item : collection) {
if (itemPasses(item))
return false;
}
return true;
}
void printIfNonePass4(const std::vector<int>& collection) {
if (checkIfNonePass(collection))
std::cout << "None pass\n";
}
int main() {
std::vector<int> collection{4,2,10,3};
printIfNonePass1(collection);
printIfNonePass2(collection);
printIfNonePass3(collection);
printIfNonePass4(collection);
}
答案 2 :(得分:1)
我喜欢通过比较迭代器和最大值
来执行不匹配场景int i;
for (i = 0; i < collectionSize; i++)
{
if (ItemPasses(collection[i]))
{
// do code for if any pass
break;
}
}
if (i == collectionSize)
{
// perform no-match operations
}
答案 3 :(得分:1)
不需要c ++ 14或c ++ 11。这样的事情应该做你想做的事。
if (find_if(collection.begin(), collection.end(), ItemPasses) == collection.end()) {
//code if none passes
}
编辑:添加c ++ 11解决方案作为对评论的回应。
if (none_of(collection.begin(), collection.end(), ItemPasses)) {
//code if none passes
}
2:编辑:回答问题。
答案 4 :(得分:0)
我认为您对算法的内部实现感兴趣,但没有应用标准算法。
通常循环按以下方式编写
CollectionType::size_type i = 0;
while ( i < collectionSize && !ItemPasses(collection[i]) ) ++i;
return ( i == collectionSize );
可以使用迭代器
编写相同的内容while ( first != last && !ItemPasses( *first ) ) ++first;
return ( first == last );
这种方法也适用于C程序。
答案 5 :(得分:-1)
在我看来,在包括的许多语言C中,控制结构没有任何正对性。 需要是显而易见的,语言应该简化程序员的工作,尽管在控制结构方面没有多少工作和/或改变的方向。
1992年,我完成了一个完整的提议和实现的正交控制结构集,可用于多种语言,并且包含了你请求的结构,这只是为了确认参数的重复性和需要的有效性。
C ++的功能虽然允许优雅的解决方案,但不能解决任何需要。
您已经提出的替代解决方案是将您需要的代码放在for构造中。因此,当函数finalizationCode()应该返回false时,代码将变得明显。
for (int i = 0; i < collectionSize ? true : finalizationCode(); i++)
放置||可能更好构造而不是if(?:)。 那么在那种情况下:
for(int i=0 ; i < collectionSize || finalizationCode() ;i++)
无论如何,只有在条件i<collectionSize
时才会执行finalizationCode
是假的。