循环通过std :: vector来查找来自std :: string数组的匹配,更简单的方法?

时间:2014-06-26 12:35:10

标签: c++ arrays windows c++11 vector

我循环遍历std :: vector和std :: string数组以查找向量中的匹配项。

示例:

#include <iostream>
#include <vector>
#include <string>


int main()
{

    std::cout << "Searching...\n";

    std::vector<std::string> myVector;

    myVector.push_back("Word");
    myVector.push_back("Word2");
    myVector.push_back("Word4");
    myVector.push_back("Word6");
    myVector.push_back("Word7");


    std::string myStringArr[] = 
    {
        "Word",
        "Word1",
        "Word2",
        "Word3",
        "Word4",
        "Word5",
        "Word6",
        "Word7"
    };

    for (auto Vec : myVector)
    {
        for(auto Str : myStringArr)
        {
            if(Vec == Str)
            {
                std::cout << "Found: " << Vec << std::endl;
            }
        }
    }


    std::cin.ignore(2);
    return 0;
}

这很好用。但我来自C语言(试图进入C ++ 11),并不确定这是否是最佳解决方案。

平台是windows,我不会(当前)使用像boost这样的外部库,正如你可以从代码中看到的那样。

是否有更好/更清洁的方法来达到相同的效果?

7 个答案:

答案 0 :(得分:1)

只要矢量和字符串数组不太长,您的解决方案就可以正常工作并且很好 对代码的改进很小:不要将auto用于简单类型,它的可读性较差(您可以使用const string&代替)。

你可以做更高效的事情:你的算法复杂度是O(NxM),N和M是矢量和数组的大小。
将向量的值存储在hash_set中,然后检查它们是否在数组中将是O(N + M)。

答案 1 :(得分:1)

如果您的数组和向量已排序,则可以使用std::set_intersection。 根据cplusplus.com,复杂性为Up to linear in 2*(count1+count2)-1 (where countX is the distance between firstX and lastX): Compares and assigns elements. 如果不是,您可以先对它们进行排序,只需O(nlog(n) + mlog(m))n为向量中的元素数,m为数组(反之亦然))时间,在线性范围之前(这比你的O(n*m)解决方案更好)。

这是它的样子:

#include <iostream>     // std::cout
#include <algorithm>    // std::set_intersection, std::sort
#include <vector>       // std::vector


  std::vector<std::string> intersection(myVector.size()); //needs to be allocated

  std::sort (myVector.begin(),myVector.end());    
  std::sort (myStringArr,myStringArr+10);   

  auto it = std::set_intersection (myVector.begin(), myVector.end(), //first range
                                   myStringArr, myStringArr+10, // second range
                                   intersection.begin()); // the result range

  v.resize(it-v.begin());                      

  std::cout << "The intersection has " << (v.size()) << " elements:\n";

答案 2 :(得分:0)

是的,您可以使用std::find_first_of

auto itVec = myVector.begin();
for (;;) {
  itVec = std::find_first_of(itVec, myVector.end(), std::begin(myStringArr), std::end(myStringArr);
  if (itVec == myVector.end())
    break;
  std::cout << "Found: " << *itVec << '\n';
  ++itVec;
}

答案 3 :(得分:0)

因为在一般情况下,矢量和数组都没有排序,所以你必须迭代每个元素。因此,这是最好的方式。

只有一件小事。 for (auto Vec : myVector)将复制每个元素。由于std::string制作浅层副本,因此您不会注意到。但在其他一些情况下,它可能是显而易见的。更好的方法是使用引用:

for (const auto& Vec : myVector)

答案 4 :(得分:0)

使用std::find_first_of

for (auto str : myStringArr)
{
    if (std::find_first_of(str, std::begin(myVector). std::end(myVector))
    {         
        std::cout << "Found: " << str << std::endl;
    }
}

答案 5 :(得分:0)

您可以使用std :: set来存储字符串:

std::set<std::string> myStringSet 
{
    "Word",
    "Word1",
    "Word2",
    "Word3",
    "Word4",
    "Word5",
    "Word6",
    "Word7"
};

for (auto Vec : myVector)
{
    if( myStringSet.count( Vec ) )
        {
            std::cout << "Found: " << Vec << std::endl;
        }
    }
}

另一种解决方案是对矢量进行排序并使用std :: binary_search:

std::vector<std::string> myStringArr 
{
    "Word",
    "Word1",
    "Word2",
    "Word3",
    "Word4",
    "Word5",
    "Word6",
    "Word7"
};
std::sort( myStringArr.begin(), myStringArr.end() );

for (auto Vec : myVector)
{
    if( std::binary_search( myStringArr.begin(), myStringArr.end(), Vec ) {
        std::cout << "Found: " << Vec << std::endl;
    }
}

答案 6 :(得分:0)

std::set_intersection算法可以满足您的需求。

使用std::sort(或使用sorted data structures)对您的两个数据结构进行排序:

std::sort(myVector.begin(), myVector.end());
std::sort(myStringArr, myStringArr + 8);

然后使用std::set_intersection

std::set_intersection(
    myVector.begin(), myVector.end(),
    myStringArr, myStringArr + 8,
    std::ostream_iterator<std::string>(std::cout, "\n"));

请注意使用std::ostream_iteratorstd::cout上打印结果。