如何在数组中找到连续的元素? C ++

时间:2015-11-05 17:36:39

标签: c++ arrays

int countconsecutive (const string a[], int n);
Return the number of sequences of one or more consecutive identical items in a.
    string d[9] = {
    "ben", "chris", "polo", "polo", "donald", "donald", "donald", "marco", "marco"
};
    int p = countRuns(d, 9);  //  returns 5


//  The five sequences of consecutive identical items are
       //    "ben"
       //    "chris"
       //    "polo", "polo"
       //    "donald", "donald", "donald"
       //    "marco", "marco"

我是否基本上必须在for循环中创建一个if语句来测试数组中两个位置之间的相等性?

3 个答案:

答案 0 :(得分:0)

以下是我在评论中提到的使用std::adjacent_find的解决方案。

#include <algorithm>

int countconsecutives(const string * a, int n)
{
    int count = 0;
    auto end = a + n; //std::begin and std::end won't work with pointers
    auto i = std::adjacent_find(a, end);
    while(i != end)
    {
        count++;
        i = std::adjacent_find(i, end);
    }

    return count;
}

使用标准算法的真正好处在于,您可以免费获得99%的边缘案例处理(在这种情况下为100%)。这已经适用于空数组和长度为1的数组。此外,如果你想将它更改为其他类似的相等的类型,你可以将字符串更改为模板,一切仍然有效(尽管其中一部分来自于使用auto)。

答案 1 :(得分:0)

您可以使用标准算法std::adjacent_find或自己编写适当的循环。

例如。

使用标准算法std :: adjacent_find

#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

size_t countconsecutive( const std::string a[], size_t n )
{
    size_t cnt = 0;

    for ( auto first = a; first != a + n; first == a + n ? first : ++first )
    {
        ++cnt;
        first = std::adjacent_find( first, a + n, std::not_equal_to<std::string>() );
    }

    return cnt;
}    

int main()
{
    std::string a[] = 
    {
        "ben", "chris", "polo", "polo", "donald", "donald", "donald", "marco", "marco"
    };

    std::cout << countconsecutive( a, sizeof( a ) / sizeof( *a ) ) << std::endl;

    return 0;
}

使用普通循环

#include <iostream>
#include <string>

size_t countconsecutive( const std::string a[], size_t n )
{
    size_t cnt = 0;

    for ( auto first = a; first != a + n; ++first )
    {
        ++cnt;

        for ( auto next = first; ++next != a + n && *first == *next; ++first );  
    }

    return cnt;
}    

int main()
{
    std::string a[] = 
    {
        "ben", "chris", "polo", "polo", "donald", "donald", "donald", "marco", "marco"
    };

    std::cout << countconsecutive( a, sizeof( a ) / sizeof( *a ) ) << std::endl;

    return 0;
}

在这两种情况下,输出都是

5

答案 2 :(得分:0)

如果您不关心阵列是否有些重新调整,可以使用std::unique为您完成所有工作:

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
    std::string a[] = 
    {
        "ben", "chris", "polo", "polo", "donald", "donald", "donald", "marco", "marco"
    };

    std::cout << std::distance(a, std::unique(a, a + sizeof(a) / sizeof(a[0]))) << std::endl;

    return 0;
}

如果你这样做,你可以使用std::unique_copy,但这显然会导致一些性能损失:

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
    std::string a[] = 
    {
        "ben", "chris", "polo", "polo", "donald", "donald", "donald", "marco", "marco"
    };


    std::vector<std::string> unique_elements;
    std::unique_copy(a, a + sizeof(a) / sizeof(a[0]), std::back_inserter(unique_elements));
    std::cout << unique_elements.size() << std::endl;

    return 0;
}

如果没有优雅的boost实施,那么答案是完整的吗?

#include <boost/range/adaptor/adjacent_filtered.hpp>
#include <boost/range/size.hpp>
#include <iostream>

int main(int argc, const char* argv[])
{
    std::string a[] = 
    {
        "ben", "chris", "polo", "polo", "donald", "donald", "donald", "marco", "marco"
    };


    std::cout << boost::size(a | boost::adaptors::adjacent_filtered(std::not_equal_to<std::string>()));

    return 0;
}