How to find the max value of group of arrays
I have six arrays which are of float
type. Any specific index in all these arrays represent set of values for me. e.g. If index is 0
all the six arrays 0
th index represent a set of values, from which I need to find the max value. Similarly, for all other indexes too.
array1 array2 array3 array4 array5 array6
0 0 0 0 开发者_JS百科0 0
1 1 1 1 1 1
And so on.
I need to find out which is the max value of a specific index among all these arrays and should store it in another array or list.
Picking up the challenge to do this in standard c++, here goes nothing.
I have tried to make the implementation of the algorithm, reduce_minelement
as generic as possible (not assuming any specific container type or number of value arrays etc.).
I provide several versions, starting with standard c++98 code (which has some kludges, mainly to get the data initialized into STL containers).
Plain standard C++98
See it live: http://ideone.com/2BlsK
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
template <typename Containers>
std::vector<typename Containers::value_type::value_type>
reduce_minelement(const Containers& containers)
{
typedef typename Containers::value_type slice_t;
typedef typename Containers::const_iterator slice_ci;
typedef typename slice_t::value_type element_t;
std::vector<element_t> result;
result.reserve(containers.size()); // pre-allocated
for (slice_ci it=containers.begin(); it!=containers.end(); ++it)
{
result.push_back(*std::max_element(it->begin(), it->end()));
}
return result;
}
typedef int ints_t[6];
static const ints_t s_data[] = {
{ 19152, 1, 21193, 17574, 8484, 30333 },
{ 20189, 18837, 30734, 2, 22440, 3534 },
{ 3, 26118, 19367, 17877, 24605, 7838 },
{ 30885, 20135, -4, 31316, 11838, 8926 },
{ 26830, 20209, 27286, 16105, 16601, 28304 },
{ 10208, 28062, 15612, 26270, 19234, 21326 },
{ 5208, 17473, 3383, 15659, 32494, 24231 },
{ 31685, 22500, 18860, 21318, 18893, 21385 },
{ 14295, 17163, 8920, 15986, 13448, 21143 },
{ 20199, 8954, 599, 17459, 3884, 8634 },
{ 16768, 20563, 6727, 26305, 11053, 6418 },
{ 7446, 6853, 5283, 6193, 28291, 4205 },
{ 27056, 17514, 5359, 29656, 10910, 6034 },
{ 21984, 1261, 2404, 17644, 25969, 1735 },
{ 797, 8457, 23584, 29363, 26362, 17383 },
{ 768, 11018, 14991, 0, 28720, 6159 },
};
int main()
{
std::vector<std::vector<int> > data;
for (const ints_t *it=s_data; it!=s_data+(sizeof(s_data)/sizeof(*s_data)); ++it)
data.push_back(std::vector<int>(*it+0, *it+sizeof(*it)/sizeof(**it)));
std::vector<int> reduced = reduce_minelement(data);
std::copy(reduced.begin(), reduced.end(), std::ostream_iterator<int>(std::cout, ", "));
return 0;
}
Plain standard C++11
Compile with c++0x support. The benefits are
- much improved initialization
- more flexibility (can be a jagged array now, see demo data)
- legibility (range-based
for
instead of iterator loops),auto
type deduction - fewer typedefs to tie things together
Note Unfortunately, because codepad.org/ideone.com uses the gcc 4.5.1 compiler, the range-based for is not yet supported; See a slightly modified version live: http://ideone.com/xevL0
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
template <typename Containers>
std::vector<typename Containers::value_type::value_type>
reduce_minelement(const Containers& containers)
{
std::vector<typename Containers::value_type::value_type> result;
result.reserve(containers.size()); // pre-allocate
for (auto& slice: containers)
result.push_back(*std::max_element(slice.begin(), slice.end()));
return result;
}
static const std::vector<std::vector<int> > data = {
{ 52, 1, 93, 74 },
{ 2, 18, 67, 77 },
{ 85, 35, -4 },
{ 48 },
{ 68, 18, 91, 0 },
};
int main()
{
auto reduced = reduce_minelement(data);
std::copy(reduced.begin(), reduced.end(), std::ostream_iterator<int>(std::cout, ", "));
return 0;
}
C++0x with Boost Range
- More concise code
- allow operating on non-STL containers (like C-style arrays) directly. This leads to slightly more complicated type deductions in
reduce_minelement
. Abstraction comes at a cost ;)
Note the data (s_data
) has been omitted because it is identical to the above; you can drop in either one of the s_data
definitions from the other examples and it would compile and run.
Note No online compiler service supports Boost library headers, so you can see this live only at home.
#include <vector>
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>
#include <iterator>
using boost::range_value;
using boost::range_iterator;
template <typename Containers>
std::vector<typename range_value<typename range_value<Containers>::type>::type>
reduce_minelement(const Containers& containers)
{
std::vector<typename range_value<typename range_value<Containers>::type>::type> result;
result.reserve(boost::size(containers)); // pre-allocate
for (auto& slice: containers)
result.push_back(*boost::max_element(slice));
return result;
}
typedef int ints_t[6];
static const ints_t s_data[] = {
{ 19152, 1, 21193, 17574, 8484, 30333 },
{ 20189, 18837, 30734, 2, 22440, 3534 },
{ 3, 26118, 19367, 17877, 24605, 7838 },
{ 30885, 20135, -4, 31316, 11838, 8926 },
{ 26830, 20209, 27286, 16105, 16601, 28304 },
{ 10208, 28062, 15612, 26270, 19234, 21326 },
{ 5208, 17473, 3383, 15659, 32494, 24231 },
{ 31685, 22500, 18860, 21318, 18893, 21385 },
{ 14295, 17163, 8920, 15986, 13448, 21143 },
{ 20199, 8954, 599, 17459, 3884, 8634 },
{ 16768, 20563, 6727, 26305, 11053, 6418 },
{ 7446, 6853, 5283, 6193, 28291, 4205 },
{ 27056, 17514, 5359, 29656, 10910, 6034 },
{ 21984, 1261, 2404, 17644, 25969, 1735 },
{ 797, 8457, 23584, 29363, 26362, 17383 },
{ 768, 11018, 14991, 0, 28720, 6159 },
};
int main()
{
boost::copy(reduce_minelement(s_data), std::ostream_iterator<int>(std::cout, ", "));
return 0;
}
Genericity: what about strings?
All three versions are fully generic towards the type of element. Some other places may need adjustment (like the ostream_iterator
type) but the actual implementation doesn't mind whether you throw float
s, std::string
s, integers
or, indeed, any comparable type at it.
Demo, based on the last version:
typedef std::string elements_t[3];
static const elements_t s_data[] = {
{ "the", "quick", "fox" },
{ "jumped", "over", "the" },
{ "lazy", "blue", "moon" },
};
int main()
{
boost::copy(reduce_minelement(s_data),
std::ostream_iterator<std::string>(std::cout, ", "));
return 0;
}
Output:
the, the, moon,
Q.E.D.
Hope this was entertaining for you. It was for me.
精彩评论