【问题标题】:How do I get characters common to two vectors in C++?如何在 C++ 中获取两个向量共有的字符?
【发布时间】:2014-02-19 01:36:27
【问题描述】:

我正在尝试比较两个向量对象,并返回一个向量,其中包含两个向量中出现的所有字符。

如果不编写一些非常复杂的手动方法,将第一个向量中的每个字符与第二个向量中的每个字符进行比较,并使用 if 将其添加到第三个向量(将被返回),我将如何处理?匹配。

也许我缺乏矢量方面的实际经验让我认为这将比实际情况更难,但我怀疑有一些更简单的方法我无法通过搜索找到。

【问题讨论】:

  • 稍微修改了标题,因为在之前的版本中,它看起来像是在寻找std::vector<t>::operator< :)

标签: c++ comparison vector


【解决方案1】:

我认为您正在寻找std::set_intersection。但是必须对源向量进行排序。如果您不关心输出向量的顺序,您始终可以在源向量的排序副本上运行它。

顺便说一句,手动幼稚的方式并不是非常复杂。给定两个源向量 s1s2,以及一个目标向量 dest,您可以编写如下所示的内容:

for (std::vector<char>::iterator i = s1.begin(); i != s1.end(); ++i)
{
    if (std::find(s2.begin(), s2.end(), *i) != s2.end())
    {
        dest.push_back(*i);
    }
}

find 步骤有很多选项,具体取决于您选择的数据结构。

【讨论】:

  • 谢谢。我期待它是这样的。
  • @BillyONEal Kristo 的回答在我发表评论时不包括该部分。
  • @Jon-Eric:事实上,确实如此。第一个修订版包含该信息。如果您不相信我,请查看编辑历史记录。
  • 好吧,伙计们,不用争论了。我通过快速连续的几次编辑来建立我的答案。显然,并非所有这些都被 SO 引擎保存为单独的修订版。
  • 重要的是要注意binary_search 要求对范围进行排序,因此只有当s2 实际上是有序的时,手动实现才会起作用。如果没有排序范围,您可以使用std::find 而不是std::binary_search,这会更慢(整个算法使用O( n^2 ))但不需要排序。
【解决方案2】:

如果我必须在两个未排序的向量上执行此操作(没有库帮助),我想我会将一个的所有元素添加到哈希表中,然后遍历第二个查找每个 - 应该比对两者都进行排序更有效也排在第一位。

【讨论】:

    【解决方案3】:
    int temp[5000]; // declare this globally if you're going to be 
                    // doing a lot of set_intersection calls   
    
    int main() {
    
      char x[]={'a','b','c','d','e'};
      char y[]={'b','c','g'};
      vector<char> v1(x,x+sizeof x/sizeof x[0]);
      vector<char> v2(y,y+sizeof y/sizeof y[0]);
      sort(v1.begin(),v1.end());
      sort(v2.begin(),v2.end());  // the vectors *must* be sorted!!!!!!
    
      vector<char> inter=vector<char>(temp,set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),temp)); // inter contains {'b','c'}
      int cnt=set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),temp) - temp;    // cnt=2
    
      for(int i = 0; i < (int)inter.size(); ++i) {
        cout<<inter[i]<<" ";
      }
      cout<<endl;
    
      return 0;
    }
    

    【讨论】:

    • 让我检查一下我是否理解这一点,因为我认为这有助于我理解自发布问题以来我发现的关于 set_intersection 的内容。 inter 包含 b 和 c,是 x 和 y 共有的字符吗?
    • @Sam Phelps - 是的,没错。并且 cnt 包含相交中元素的数量(我只是把它放在那里,以防您出于某种原因只需要获取相交元素的数量)。
    • 使用插入迭代器可能更清楚,而不是为目标向量分配固定大小的数组。
    【解决方案4】:

    使用set_intersection。这是一个工作示例:

    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int main()
    {
        vector<string> v1;
        v1.push_back("Mary");
        v1.push_back("had");
        v1.push_back("a");
    
        vector<string> v2;
        v2.push_back("a");
        v2.push_back("little");
        v2.push_back("lamb");
    
        sort(v1.begin(), v1.end());
        sort(v2.begin(), v2.end());
    
        vector<string> v3;
        set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(v3));
    
        copy(v3.begin(), v3.end(), ostream_iterator<string>(cout, "\r\n"));
        return 0;
    }
    

    【讨论】:

      【解决方案5】:

      这并不能很好地超出标准 char 类型(可能是 unicode,具体取决于应用程序),但如果您有兴趣在 O(n) 时间内完成此操作,这应该可行。

      
      #include <vector>
      #include <string>
      #include <iostream>
      
      std::vector<char> intersect(const std::vector<bool>& x,
                                  const std::vector<bool>& y)
      {
          std::vector<char> rv;
      
          std::vector<bool>::const_iterator ix, iy;
          size_t i;
      
          for (i=0, ix = x.begin(), iy = y.begin();
               ix != x.end() && iy != y.end();
               ++i, ++ix, ++iy)
              if (*ix && *iy) rv.push_back( (char) i);
      
          return rv;
      }
      
      std::vector<bool> poll(const std::vector<char>& x)
      {
          std::vector<bool> rv(256, false);
      
          for (std::vector<char>::const_iterator i = x.begin(); i != x.end(); ++i)
              rv[*i] = true;
      
          return rv;
      }
      
      std::vector<char> build(const std::string& val)
      {
          std::vector<char> rv;
      
          for (size_t i = 0; i < val.size(); ++i)
              rv.push_back(val[i]);
      
          return rv;
      }
      
      int main(int argc, char *argv[])
      {
          std::vector<char> x1 = build("The Quick Brown Fox Jumps Over The Lazy Dog");
          std::vector<char> x2 = build("Oh give me a home where the buffalo roam");
      
          std::vector<char> intersection = intersect(poll(x1), poll(x2));
      
          for (std::vector<char>::iterator i=intersection.begin();
                  i != intersection.end(); ++i)
              std::cout << *i;
      
          std::cout << std::endl;
      
          return 0;
      }
      

      【讨论】:

        【解决方案6】:

        因为从您后面的问题中可以看出,您实际上只关心 26 个字符:

        std::bitset<26> in;
        for (std::vector<char>::iterator it = first.begin(); it != first.end(); ++it) {
            in[*it - 'a'] = true;
        }
        for (std::vector<char>::iterator it = second.begin(); it != second.end(); ++it) {
            if (in[*it - 'a']) {
                result.push_back(*it);
                // this line is only needed if 'second' can contain duplicates
                in[*it - 'a'] = false;
            }
        }
        

        事实上,bitset&lt;UCHAR_MAX&gt; 在几乎所有架构上都很小。请注意那些具有 32 位字符的 DSP,并谨慎地将这种技术应用于wchar_t

        使用 BOOST_FOREACH,代码看起来更合理:

        assert(UCHAR_MAX <= 512 && "What kind of crazy machine is this?");
        std::bitset<UCHAR_MAX> in;
        
        BOOST_FOREACH(unsigned char c, first) {
            in[c] = true;
        }
        
        BOOST_FOREACH(unsigned char c, second) {
            if (in[c]) {
                result.push_back(c);
                // this line is only needed if 'second' can contain duplicates
                in[c] = false;
            }
        }
        

        【讨论】:

          【解决方案7】:

          如果你有字符,也许你应该使用 std::strings 而不是向量?字符串有很多搜索等功能。

          【讨论】:

            猜你喜欢
            • 2019-11-24
            • 1970-01-01
            • 2021-11-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-10
            • 2014-01-21
            • 1970-01-01
            相关资源
            最近更新 更多