C++ 如何在C+;中的字符串向量中找到重复的单词+;?

C++ 如何在C+;中的字符串向量中找到重复的单词+;?,c++,string,vector,C++,String,Vector,我有一个std::vector,其中每个元素都是一个单词。我想打印不重复单词的矢量 我在网上搜索了很多资料,但我找不到,我不想使用散列图、迭代器和“高级”(对我来说)的东西。我只能使用纯字符串比较=,因为我还是个初学者 因此,让my_vecastd::vector从std输入初始化。我的想法是阅读所有矢量,并在找到后删除任何重复的单词: for(int i=0;i<my_vec.size();++i){ for (int j=i+1;j<my_vec.size();++j

我有一个
std::vector
,其中每个元素都是一个单词。我想打印不重复单词的矢量

我在网上搜索了很多资料,但我找不到,我不想使用散列图、迭代器和“高级”(对我来说)的东西。我只能使用纯字符串比较
=
,因为我还是个初学者

因此,让
my_vec
a
std::vector
从std输入初始化。我的想法是阅读所有矢量,并在找到后删除任何重复的单词:

  for(int i=0;i<my_vec.size();++i){
    for (int j=i+1;j<my_vec.size();++j){
      if(my_vec[i]==my_vec[j]){
        my_vec.erase(my_vec.begin()+j); //remove the component from the vector
      }
    }
  }
for(inti=0;i为什么不使用

您可以简单地使用它,如下所示:

std::vector v{“你好”、“你好”、“你好”、“你好”、“你好”};
排序(v.begin(),v.end());
v、 擦除(std::unique(v.begin()、v.end()、v.end());
N.B.需要对元素进行排序,因为
std::unique
仅适用于连续的重复项


如果您不想更改std::vector的内容,但只有稳定的输出,我推荐其他答案。

从循环中的容器中删除元素有点棘手,因为在删除索引
I
处的元素后,下一个元素(在下一次迭代中)不是在索引
i+1
处,而是在索引
i

阅读有关擦除删除习惯用法的信息,该习惯用法用于以idomatic方式擦除元素。但是,如果您只想在屏幕上打印,有一种更简单的方法来修复代码:

for(int i=0; i<my_vec.size(); ++i){
   bool unique = true;
   for (int j=0; j<i; ++j){
       if(my_vec[i]==my_vec[j]) {
           unique = false;
           break; 
       }
       if (unique) std::cout << my_vec[i];
   }
}

for(int i=0;i您可以简单地使用
sort
unique
的组合,如下所示

#include <iostream>
#include <algorithm>
#include <vector>

int main() {
    std::vector<std::string> vec{"hey","how","are","you","fine","and","you","fine"};
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end() ), vec.end());
    
    for (int i = 0; i < vec.size(); i ++) {
        std::cout << vec[i] << " ";
    }
    std::cout << "\n";

    return 0;
}
#包括
#包括
#包括
int main(){
向量向量{“嘿”、“怎么样”、“是”、“你”、“很好”、“和”、“你”、“很好”};
排序(vec.begin(),vec.end());
擦除向量(唯一(vec.begin()、vec.end()、vec.end());
对于(int i=0;istd::cout您可以存储要擦除的元素索引,然后在最后将其删除。
或重复该循环,直到不执行擦除。

第一个代码示例:

std::vector<int> index_to_erase();

for(int i=0;i<my_vec.size();++i){
    for (int j=i+1;j<my_vec.size();++j){
      if(my_vec[i]==my_vec[j]){
        index_to_erase.push_back(j);
        
      }
    }
  }
//starting the cycle from the last element to the vector of index, in this 
//way the vector of element remains equal for the first n elements
for (int i = index_to_erase.size()-1; i >= 0; i--){
   my_vec.erase(my_vec.begin()+index_to_erase[i]); //remove the component from the vector
} 
bool Erase = true;
while(Erase){
  Erase = false;
  for(int i=0;i<my_vec.size();++i){
    for (int j=i+1;j<my_vec.size();++j){
      if(my_vec[i]==my_vec[j]){
        my_vec.erase(my_vec.begin()+j); //remove the component from the vector
        Erase = true;
      }
    }
  }
}
std::向量索引到擦除();

对于(int i=0;i现有代码的最简方法,
j
的自动增量最终会破坏您的算法。不要这样做。相反,只在不删除元素的情况下增加它

for(int i=0;i


这就是字面意思。

讽刺的是,
std::vector::erase
通过返回一个新的迭代器来解决这个问题。你可以通过抵消
++j
来模拟这个问题。你真的应该至少使用迭代器,因为这样做可以字面上解决你的问题,同时以最温和的方式推广你应该做的事情一开始是长期的(即迭代器;标准库实际上是靠迭代器生存和消亡的)。如果单词的顺序改变了可以吗?或者你需要按照它们存储在向量中的顺序打印它们吗?更简单的解决方案是创建一个新的重复的自由向量。@idclev463035818是的,如果单词的顺序改变了也可以。啊,我忘了添加需要排序的内容。正如我理解的问题,输出应该是稳定的,即排序替代选项(除非之后恢复原始顺序)@idclev463035818啊,我不是从问题中得到的,但很可能你是right@NutCracker正如idclev所指出的,我只是对不重复的打印感兴趣,忽略排序!顺便说一句,我不知道std::unique,谢谢:)事实证明我错了。事实上,我更希望你不要引用我的答案,因为还有更好的答案(包括这个)你为什么对向量进行排序?我没找到这个point@Vefhug如果没有排序,
std::unique
将无法按预期工作。好的,现在我明白了:
std::unique
只对连续的重复项起作用。不,它起作用是因为我开始从最后一个索引中删除元素,这将确保前n个元素不会更改其索引ybe太聪明了,它需要一个注释或一点解释。第一段代码中的方法是我尝试的另一种方法,但我停止了,因为我不能只删除与一组整数对应的值,但我真的很喜欢你从底部开始的方法@ZigRazor@Vefhug从
索引到\u擦除的循环是cod的一部分e这会从你的向量中删除元素。@ZigRazor是的,我意识到了,我只是说它是我之前结巴的地方:)现在它非常清楚了。非常感谢你的回答,这正是我想要的。顺便说一句,我正试图跟踪重复的次数:我定义了一个长度为my_vec.size()的动态数组
repts
我做
报告[I]++
if
中。但是,我没有得到正确的结果。有什么问题吗@WhozCraig@Vefhug说起来很难,但实际上看不到你是怎么做的。坦率地说,我会使用
std::unordered_map
,但是如果你真的同意并排向量的想法,我现在可以尝试使用
std::un有序映射
,但我真的不明白怎么做,因为我从未使用过它。你如何使用它完成任务?@Vefhug有趣的是,你应该问..这种方法的关键是映射到映射中的新元素的值初始化;它是零。因此,
++m[*it]
仅在第一次插入时才是
1
(因此我们跳过从向量中删除)。否则,它将大于1,我们(a)在映射中保持更新的计数,并且(b)知道我们需要从向量中删除该实例。老实说,你甚至不需要向量,除非你想保留原始向量顺序(你需要)。我不知道这样做,谢谢。@WhozCraig可以
for (int i = 0; i < my_vec.size(); ++i) {
    for (int j = i + 1; j < my_vec.size(); ) {  // NOTE: no ++j
        if (my_vec[i] == my_vec[j]) {
            my_vec.erase(my_vec.begin() + j);
        }
        else ++j; // NOTE: moved to else-clause
    }
}