# C ++ checking an array for a specific range of values?

I would like to check an array for a specific range of values. those. the range of values ​​is 0 to> 9, and the actual array is 50 elements.

I also want to keep track of how much of each value is there. those. if there are 3 zeros, 8 ones and 5 two, then my last vector should look like this: 3 8 5.

i was able to solve it with below code BUT, i figured out that my range values ​​must be equal to the size of my array, otherwise it doesn't check all elements.

Is there a better way to do this?

``````int main() {

int intensityRange = 10;
int cloudSize = 10;

int cloud [] = {0, 3, 3, 2, 1, 5, 2, 3, 5, 2};
vector <int> totalGreyValues;
int k = 0;

for (int i = 0; i < intensityRange; i++) {
for (int j = 0; j < cloudSize; j++) {
if (cloud[j] == i) {
k = k + 1;
cout << "   " << k;
}
else
cout << "  no match  ";
}
totalGreyValues.push_back (k);
k = 0;
}

cout << endl << endl << totalGreyValues.size();

for (int h = 0; h < totalGreyValues.size(); h ++)
cout << "   " << totalGreyValues[h];

// values --> 0 1 2 3 4 5 6 7 8 9
// answer --> 1 1 3 3 0 2 0 0 0 0

return 0;
}
```

```
+3

source to share

Much easier to use `std::map`

:

``````int size = 50;
int data[size] = { 1, 2, 3, 4, 5, ... };

std::map<int, int> mymap;

for(int i = 0; i < size; i++)
{
if(data[i] >= min && data[i] <= max)
mymap[data[i]] = mymap[data[i]] + 1;
}
```

```

This saves some space because you are not saving unused values, and the number of loops is also much less because you only process once per value.

+4

source

If your range is contiguous, I would prefer boost :: vector_property_map .

``````#include <boost/property_map/vector_property_map.hpp>
#include <iostream>

int main()
{
boost::vector_property_map<unsigned int> m(10); // size of expected range

std::vector<int> cloud = {0, 3, 3, 2, 1, 5, 2, 3, 5, 2};
for(auto x : cloud) { m[x]++; }
for(auto it = m.storage_begin(); it != m.storage_end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;

return 0;
}
```

```

If your range does not start with `0`

, you can use the template `IndexMap`

argument to reassign the indices. This will also work if you are a continuous set of values ​​that you want to convert to a continuous assortment. You may need to do a check if you only want to count but given the high cost of counting operations, I would rather count them all rather than check what to count.

0

source

Use a function `std::map`

and `std::accumulate`

:

``````#include <map>
#include <algorithm>

typedef std::map<int, int> Histogram;

Histogram& addIfInRange(Histogram& histogram, const int value)
{
if(inRange(value))
{
++histogram[value];
}

return histogram;
}

Histogram histogram =
std::accumulate(data, data + size, Histogram(), addIfInRange);
```

```
0

source

If you have enough free scopes, you can try the multiset along with some new C ++ features:

``````#include <set>
#include <iostream>

int main () {
int vals[] = { 0, 1, 2, 3, 4, 5, 5, 5, 6 };

std::multiset <int> hist;
for (auto const &v : vals)
if (v >= 3 && v <= 5) hist.insert (v);

for (auto const &v : hist)
std::cout << v << " -> " << hist.count (v) << '\n';
}
```

```

If your data is densely populated, `std::vector`

may give better results:

``````#include <algorithm>
#include <iostream>

int main () {
using std::begin; using std::end;

int vals[] = { 1, 2, 4, 5, 5, 5, 6 };

const auto val_mm  = std::minmax_element (begin(vals), end(vals));
const int  val_min = *val_mm.first,
val_max = *val_mm.second + 1;

std::vector<int> hist (val_max - val_min);

for (auto v : vals)
++hist [v - val_min];

for (auto v : vals)
std::cout << v << " -> " << hist[v-val_min] << '\n';
}
```

```
0

source

All Articles