C++ 计算向量中的出现次数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1204313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:10:24  来源:igfitidea点击:

Counting occurrences in a vector

c++

提问by trikker

This program reads strings of numbers from a txt file, converts them to integers, stores them in a vector, and then tries to output them in an organized fashion like so....

该程序从 txt 文件中读取数字字符串,将它们转换为整数,将它们存储在一个向量中,然后尝试以有组织的方式输出它们,就像这样......

If txt file says:

如果txt文件说:

7 5 5 7 3 117 5

The program outputs:

程序输出:

3
5   3
7   2
117

so if the number occurs more than once it outputs how many times that happens. Here is the code so far.

所以如果这个数字出现不止一次,它会输出发生了多少次。这是到目前为止的代码。

#include "std_lib_facilities.h"

int str_to_int(string& s)
{
    stringstream ss(s);
    int num;
    ss >> num;
    return num;
}

int main()
{
    cout << "Enter file name.\n";
    string file;
    cin >> file;
    ifstream f(file.c_str(), ios::in);

    string num;
    vector<int> numbers;
    while(f>>num)
    {
        int number = str_to_int(num);
        numbers.push_back(number);
    }

    sort(numbers.begin(), numbers.end());

    for(int i = 0; i < numbers.size(); ++i)
    {
     if(i = 0 && numbers[i]!= numbers[i+1]) cout << numbers[i] << endl;
     if(i!=0 && numbers[i]!= numbers[i-1])
     {
          cout << numbers[i] << '\t' << counter << endl;
          counter = 0;
     }
     else ++counter;
    }
 }

Edit: Program is getting stuck. Looking for an infinite loop right now.

编辑:程序卡住了。现在正在寻找无限循环。

采纳答案by bstpierre

How about using a map, where the key is the number you're tracking and the value is the number of occurrences?

如何使用地图,其中键是您要跟踪的数字,而值是出现的次数?

If you must use a vector, you've already got it sorted. So just keep track of the number you previously saw. If it is the same as the current number, increment the counter. Every time the number changes: print out the current number and the count, reset the count, set the last_seen number to the new number.

如果您必须使用向量,那么您已经对它进行了排序。因此,只需跟踪您之前看到的数字即可。如果它与当前数字相同,则增加计数器。每次数字变化时:打印出当前数字和计数,重置计数,将 last_seen 数字设置为新数字。

回答by Adam Holmberg

You could use a map of numbers to counters:

您可以使用数字映射来计算:

typedef map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
   CounterMap::iterator it(counts.find(numbers[i]));
   if (it != counts.end()){
      it->second++;
   } else {
      counts[numbers[i]] = 1;
   }
}

... then iterate over the map to print results.

...然后遍历地图以打印结果。

EDIT: As suggested by lazypython: if you have the TR1 extensions[wikipedia.org] available, unordered_map should have better performance...

编辑:正如lazypython所建议的:如果你有可用的TR1扩展[wikipedia.org],unordered_map应该有更好的性能......

typedef std::tr1::unordered_map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
   CounterMap::iterator it(counts.find(numbers[i]));
   if (it != counts.end()){
      it->second++;
   } else {
      counts[numbers[i]] = 1;
   }
}

回答by AraK

Using a map is the practicalsolution. What you should do is to solve this problem :)

使用地图是实用的解决方案。你应该做的是解决这个问题:)

This is called frequency counter. So, you have a sorted vector and all what you have to do is to count successive equal numbers. In other words, you have to check each number with its successor.

这称为频率计数器。所以,你有一个排序的向量,你所要做的就是计算连续的相等数字。换句话说,您必须检查每个数字及其后继数字。

for(size_t i = 0; i < numbers.size(); i++)
{
    size_t count = 1;

    size_t limit = numbers.size() - 1;
    while(i < limit  && numbers[i] == numbers[i+1])
    {
        count++;
        i++;
    }

    std::cout << numbers[i] << "\t" << count << std::endl;
}   

回答by SingleNegationElimination

This program reads strings of numbers from a txt file, converts them to integers, stores them in a vector, and then tries to output them in an organized fashion like so....(emphasis added)

该程序从 txt 文件中读取数字字符串,将它们转换为整数,将它们存储在一个 vector 中,然后尝试像这样以有组织的方式输出它们...... (强调)

What is the point of this storage step? If you are reading the numbers from a file, then you already have them in order, ready to be processed (counted) one at time, as you encounter them.

这个存储步骤的重点是什么?如果您正在从文件中读取数字,那么您已经将它们按顺序排列好,可以在遇到它们时一次处理(计数)一个。

However, I would need a way for it to know when it sees a new number.

但是,我需要一种方法来让它知道何时看到新号码。

I advise you to have a look at std::setor std::map. I expect either of these containers would do what you're looking for.

我建议你看看std::setstd::map。我希望这些容器中的任何一个都能满足您的需求。

回答by D.Shawley

Std::count()fits the bill nicely.

Std::count()很合算。

std::vector<int>::const_iterator cur = numbers.begin();
std::vector<int>::const_iterator last = numbers.end();
while (cur != last) {
    unsigned cnt = std::count(cur, last, *cur);
    std::cout << *cur;
    if (cnt != 1) {
        std::cout << " " << c;
    }
    std::cout << std::endl;
    int saved = *cur;
    while (*cur == saved) {
        ++cur;
    }
}

Of course there are a bunch of other algorithms out there that will do the same job. Play with things like std::equal_range()in conjunction with std::distance()will do the job just as nicely.

当然,还有很多其他算法可以做同样的工作。将诸如 with 之类的东西std::equal_range()一起玩std::distance()也能很好地完成工作。

回答by Martin York

That was fun:

蛮好玩的:

#include <map>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>

struct IncrementMap
{
    IncrementMap(std::map<int,int>& m): m_map(m)    {}
        void operator()(int val) const
    {
        ++m_map[val];
    }
    std::map<int,int>& m_map;
};
struct SpecialPrint
{
    SpecialPrint(std::ostream& s):  m_str(s)    {}
    void operator()(std::map<int,int>::value_type const& value) const
    {
        m_str << value.first;
        if (value.second != 1)
        {
            m_str << "\t" << value.second;
        }
        m_str << "\n";
    }
    std::ostream&   m_str;
};
int main()
{
    std::fstream        x("Plop");
    std::map<int,int>   data;

    std::for_each(  std::istream_iterator<int>(x),
                     std::istream_iterator<int>(),
                     IncrementMap(data)
                );
    std::for_each(  data.begin(),
                    data.end(),
                    SpecialPrint(std::cout)
                );
}