I want to check if a vector of integers has any duplicates or not, and have to return true if it does. So I try to do something like this:
vector<int> uGuess = {1,2,3,3,4,5}
vector<int> a = uGuess;
sort(a.begin(), a.end());
bool d = unique(a.begin(), a.end());
And this will not work since unqiue cannot be assigned as a bool value.
How should I proceed towards this?
If I were to write a for loop to perform the same action, how should I do that?
The algorithm you're looking for is std::adjacent_find.
// The container must be sorted!
const std::vector<int> sortedVector = {1,2,3,3,4,5};
const bool hasDuplicates = std::adjacent_find(sortedVector.begin(), sortedVector.end()) != sortedVector.end();
Unlike std::unique, std::adjacent_find doesn't modify the container.
As a bonus, std::adjacent_find returns an iterator to the first element in the duplicate "pair":
const auto duplicate = std::adjacent_find(sortedVector.begin(), sortedVector.end());
if (duplicate != sortedVector.end())
std::cout << "Duplicate element = " << *duplicate << "\n";
Looking at google for std::unique I found this page std::unique. I looked at what it did:
Eliminates all except the first element from every consecutive group of equivalent elements from the range [first, last)
So it looks like it does what you want - removes the duplicates.
I then looked at what it returns...
... returns a past-the-end iterator for the new logical end of the range
So the result from std::unique is a sequence which is not necessary the same as the whole vector.
If nothing was removed, the return value would be the end of the vector.
So you want:
vector<int>::iterator it = std::unique(a.begin(), a.end());
bool wasUnique = (it == a.end());
Or for C++11:
auto it = std::unique(a.begin(), a.end());
bool wasUnique = (it == a.end());
Finally for the unique function to work, the vector needs to be sorted, so the complete code would be:
sort(a.begin(), a.end());
auto it = std::unique(a.begin(), a.end());
bool wasUnique = (it == a.end());
You should using set
set<int> s(a.begin(), a.end());
return s.size() != a.size();
If someone is forced to write own algorithm:
bool hasDuplicates(const std::vector<int>& arr) {
for (std::size_t i = 0; i < arr.size(); ++i) {
for (std::size_t j = i + 1; j < arr.size(); ++j) {
if (arr[i] == arr[j])
return true;
}
}
return false;
}
But in real code you should use things that already exist, and in the standard library.
Sort the vector if it's not already sorted, and then use std::unique(), like this:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {3, 1, 3, 4, 5};
sort(v.begin(), v.end());
auto it = std::unique(v.begin(), v.end());
std::cout << ((it == v.end()) ? "Unique\n" : "Duplicate(s)\n");
return 0;
}
Output:
Duplicate(s)
So far all these solutions either modify the container or have O(n²) complexity. You can put a std::map to much better use:
#include <algorithm>
#include <iterator>
#include <map>
template <typename Iterator>
bool has_duplicates( Iterator first, Iterator last )
{
std::map <typename std::iterator_traits <Iterator> ::value_type, std::size_t> histogram;
while (first != last)
if (++histogram[ *first++ ] > 1)
return true;
return false;
}
#include <iostream>
#include <vector>
int main()
{
using std::begin;
using std::end;
int a[] = { 2, 3, 5, 7, 11 };
int b[] = { 2, 3, 5, 5, 7 };
std::vector <int> c( begin(a), end(a) );
std::vector <int> d( begin(b), end(b) );
std::cout << std::boolalpha;
std::cout << "a has duplicates false : " << has_duplicates( begin(a), end(a) ) << "\n";
std::cout << "b has duplicates true : " << has_duplicates( begin(b), end(b) ) << "\n";
std::cout << "c has duplicates false : " << has_duplicates( begin(c), end(c) ) << "\n";
std::cout << "d has duplicates true : " << has_duplicates( begin(d), end(d) ) << "\n";
}
If your vector is small, say < 32 objects, or if copying and sorting the objects is expensive or impossible due to lack of move or copy constructor/assignment then a straight O(n^2) compare everything against everything else algorithm is the way to go.
Here is my solution:
template <typename Iterator>
bool has_duplicates( Iterator first, Iterator end ) {
for (auto i = first; i != end; ++i) {
for (auto j = first; i != j; ++j) {
if (*i == *j) return true;
}
}
return false;
}
template <typename Container>
bool has_duplicates(const Container &v) {
for (const auto & i : v) {
for (const auto & j : v) {
if (&i == &j) break;
if (i == j) return true;
}
}
return false;
}
Related
can someone come up with a clean (and fast) solution to the following problem:
I have a sequence of entries that hold basically a key and a value, say a
struct Value {
int index = 0;
int cost = 0;
}
I now want to merge entries such that each key is only contained once but the values should be combined - i.e. each index should be only contained once in the sequence, and the cost for each duplicate index should be accumulated.
The basic solution I came up with sorts the sequence, and when equal entries are detected in the BinaryPredicate passed to std::sort, the cost will be summed into the lhs. Then the cost of rhs will be set to 0. Then follows a remove_if which removes the 0-cost values. See here for an example:
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iostream>
struct Value
{
int index = 0;
int cost = 0;
};
// generate a bunch of random values in a vector
// values will have indices in range [0..10]
std::vector<Value> generator()
{
std::vector<Value> v(20);
std::generate(v.begin(), v.end(), []() { return Value{std::rand() % 10, std::rand() % 10}; });
return v;
}
void print(const std::vector<Value> &values)
{
for (auto v : values)
std::cout << "{i=" << v.index << ", c=" << v.cost << "}, ";
std::cout << "\n";
}
//
void merge(std::vector<Value> &values)
{
// sort values and merge costs
std::sort(values.begin(), values.end(), [](auto &lhs , auto &rhs) {
if (lhs.index == rhs.index) {
lhs.cost += rhs.cost;
rhs.cost = 0;
}
return lhs.index < rhs.index;
});
// remove entries with empty cost
auto it = std::remove_if(values.begin(), values.end(), [](const auto &v) { return v.cost == 0; });
values.erase(it, values.end());
}
int main()
{
auto v = generator();
std::cout << "generated values: ";
print(v);
merge(v);
std::cout << "merged values: ";
print(v);
}
Live on Compiler Explorer
Thing is: While the example above produces the correct results, it is from what I can tell not conforming to the C++ standard. A BinaryPredicate "shall not apply any non-constant function through the dereferenced iterators" http://eel.is/c++draft/algorithms.requirements#8.sentence-4 . Compare is a BinaryPredicate. http://eel.is/c++draft/alg.sorting#general-2.sentence-1 )
Does this mean that my only option is to roll a custom inplace_unique_reduce or similar, or is there maybe an alternative elegant approach to this problem? I would prefer not having to write my own non-trivial algorithm for this.
Thanks
Assuming you are ok with additional allocations, I would use std::map (or the std::unordered_map):
auto merge_entries(std::vector<Value>& original_values) {
auto values = std::map<int, int>();
for (const auto [index, cost] : original_values) {
values[index] += cost;
}
const auto end_of_merged_values = std::transform(
values.cbegin(), values.cend(), original_values.begin(),
[](const auto entry) {
return Value{entry.first, entry.second};
}
);
original_values.erase(end_of_merged_values, original_values.end());
}
Apart from one for() loop (which can be substituted with std::for_each, although such change would introduce unnecessary boilterplate resulting in harder to read code, in my opinion), this solution uses only the STL.
We first merge all the entries using the map and then we overwrite some elements so that our original std::vector holds the merged entries. What's super convenient is the fact that std::transform returns an iterator pointing to the end of the inserted range. Why is it beneficial for us? Because apart from the unlikely scenario where no merging occurs, we have fewer elements compared to what was originally passed in. Using that iterator we can erase the rest of the vector (nonoverwritten elements) keeping it clean, STL-like style.
Assuming you are not ok with additional allocations, but you are ok with streghtening your iterator requirements (to bidirectional), I would use std::partial_sum and std::unique:
template <class BiDirIt, class BinaryPredicateCompare, class BinaryOpReduce>
auto inplace_unique_reduce(
BiDirIt first, BiDirIt last,
BinaryPredicateCompare cmp,
BinaryOpReduce reduce
) {
std::partial_sum(
std::make_reverse_iterator(last), std::make_reverse_iterator(first),
std::make_reverse_iterator(last),
[cmp, reduce](auto acc, const auto& elem) {
if (cmp(acc, elem)) {
return reduce(acc, elem);
} else {
acc = elem;
}
return acc;
}
);
return std::unique(first, last, cmp);
}
used like so:
auto values = std::vector<Value>{
{1, 1}, {2, 2}, {2, 7}, {0, 5},
{3, 3}, {1, 2}, {3, 10}
};
auto comparator = [](const auto& lhs, const auto& rhs) {
return lhs.index == rhs.index;
};
auto reducer = [](const auto& lhs, const auto& rhs) {
return Value{lhs.index, lhs.cost + rhs.cost};
};
auto to_remove = inplace_unique_reduce(
values.begin(), values.end(),
comparator,
reducer
);
values.erase(to_remove, values.end());
for (const auto[index, cost] : values) {
std::cout << index << ' ' << cost << '\n';
}
Just like your original answer, this will not merge nonadjacent elements, but to do that you either have to sort them by index or use something like map, from the first part of my answer.
The std::make_reverse_iterator calls are necessary becauase std::partial_sum accumulates the merged element in the most right-hand side one of given group of consecutive, equivalent elements. std::unique, on the other hand, preserves only the first element from such groups. Because of this, you want to merge the elements in the reverse order compared to the one you will be std::unique-ing.
You raised some concerns about situations where copying or moving is expensive - in such cases, you are either left with your custom solutions that take into considerations your unique constraints, or you ease your constraints. Here we move-assign merged entries, but that's it for the potential bottlenecks. If your move assignment operator is expensive, I fear that no standard solution will work for you and you have to roll your own, like in your answer.
This is the best I can come up with so far, but I still wonder if there is a solution that does not require a custom algorithm but instead combines existing ones:
template <class ForwardIt, class BinaryPredicateCompare, class BinaryOpReduce>
ForwardIt inplace_unique_reduce(ForwardIt first, ForwardIt last, BinaryPredicateCompare cmp, BinaryOpReduce reduce)
{
if (first == last)
return last;
ForwardIt result = first;
while (++first != last) {
if (cmp(*result, *first)) {
reduce(*result, *first);
} else if (++result != first) {
*result = std::move(*first);
}
}
return ++result;
}
Personally I would be much happier to modify the objects inside the Predicate of remove_if, since it is a much simpler and more straight-forward algorithm than sort. It does require keeping track of the output index, though:
void merge(std::vector<Value> &values)
{
std::sort(values.begin(), values.end(), [](auto &lhs , auto &rhs) { return lhs.index < rhs.index; });
std::size_t o_i = 0;
auto it = std::remove_if(values.begin(), values.end(), [&](const auto &v) {
if(o_i > 0 && values[o_i-1].index == v.index)
{
values[o_i-1].cost += v.cost;
return true;
}
o_i++;
return false; });
values.erase(it, values.end());
}
Here's another version using the range-v3 library (std::ranges doesn't have group_by yet).
#include <range/v3/all.hpp>
void merge(std::vector<Value> &values)
{
std::sort(values.begin(), values.end(), [](auto &lhs, auto &rhs) { return lhs.index < rhs.index; });
auto merged = values
| ranges::v3::view::group_by([](Value &lhs, Value &rhs) { return lhs.index == rhs.index; })
| ranges::v3::view::transform([](auto &&vs){
int index, cost = 0;
for(auto& v : vs) { index=v.index; cost+=v.cost;}
return Value{index, cost};
});
auto it = ranges::v3::copy(merged.begin(), merged.end(), values.begin()).second;
values.erase(it, values.end());
}
Also, don't forget plain old for-loop:
void merge(std::vector<Value> &values)
{
std::sort(values.begin(), values.end(), [](auto &lhs , auto &rhs) { return lhs.index < rhs.index; });
std::size_t j = 0;
for(std::size_t i = 0; i < values.size(); i++)
{
if(j>0 && values[j-1].index == values[i].index)
{
values[j-1].cost += values[i].cost;
continue;
}
if(j!=i) values[j]=std::move(values[i]);
j++;
}
values.erase(values.begin()+j, values.end());
}
Lets say I have a vector<int> { 1, 1, 2, 3, 3, 3, 1, 1 } and I'd like to convert this into a vector<std::pair<int, int>> { {1, 2}, {2, 1}, {3, 3}, {1, 2} } of 'adjacent element counts':
I'd probably iterate over the vector with a flag indicating the start of a new 'adjacency set' and a counter which counts the number of consecutive elements. I was just wondering if there isn't already a more abstract and elegant solution in the STL as this seems like a very common use-case. Algorithms like unique, adjacent_find or equal_range seem pretty close to what I'm looking for but just not quite the right thing and probably no gain to implementing it from scratch myself.
From an algorithmic point of view the closest thing is run-length encoding I would say. I don't think there is a ready made algorithm to do that, but the code should be trivial:
std::vector<std::pair<int, int>> out;
for (int i: in)
{
if (out.empty() || out.back().first != i)
{
out.emplace_back(i, 1);
}
else
{
++out.back().second;
}
}
Live-example.
Eric Niebler's range library, which, AFAIU is in the process of becoming part of the standard library, has a group_by which is very similar to Python's itertools.groupby, and groups consecutive equivalent elements, just as you need.
To group your vector, you'd start with
const vector<int> l{ 1, 1, 2, 3, 3, 3, 1, 1 };
auto x = l | view::group_by(std::equal_to<int>());
which means that x is a view where adjacent integers belong to a group, if the integers are equal.
Now to iterate, and say, print each consecutive group and its size, you could do the following (I'm sure you can do it better than the following, but this is the limit of my use of this library):
for (auto i = x.begin();i != x.end(); ++i)
cout << *((*i).begin()) << " " << to_vector(*i).size() << endl;
Example
#include <vector>
#include <iostream>
#include <range/v3/all.hpp>
int main(int argc, char **argv) {
const std::vector<int> l{ 1, 1, 2, 3, 3, 3, 1, 1 };
auto x = l | ranges::view::group_by(std::equal_to<int>());
for (auto i = x.begin();i != x.end(); ++i)
std::cout << *((*i).begin()) << " " << ranges::to_vector(*i).size() << std::endl;
}
This prints out
$ ./a.out
1 2
2 1
3 3
1 2
As far as I know there is no such C++ library that will automatically do what you are asking.
Anyway, it is very simple to implement this though. Here is one way:
#include <iostream>
#include <vector>
using namespace std;
void count_equal_elements(vector<int>& vec, vector<pair<int,int> >& result){
if (vec.empty())
return;
int curr = vec[0];
int count = 1;
for (vector<int>::iterator it = vec.begin()+1; it != vec.end(); ++it){
if (curr == *it){
count++;
}
else{
result.push_back(make_pair(curr,count));
curr = *it;
count = 1;
}
}
result.push_back(make_pair(curr,count));
}
See it in ideone.
With std, you may do:
template <typename T>
std::vector<std::pair<T, std::size_t>>
adjacent_count(const std::vector<T>& v)
{
std::vector<std::pair<T, std::size_t>> res;
for (auto it = v.begin(), e = v.end(); it != e; /*Empty*/) {
auto it2 = std::adjacent_find(it, e, std::not_equal_to<>{});
if (it2 != e) {
++it2;
}
res.emplace_back(*it, std::distance(it, it2));
it = it2;
}
return res;
}
Demo
or
template <typename T>
std::vector<std::pair<T, std::size_t>>
adjacent_count(const std::vector<T>& v)
{
std::vector<std::pair<T, std::size_t>> res;
for (auto it = v.begin(), e = v.end(); it != e; /*Empty*/) {
const auto it2 = std::find_if(it, e, [&](const auto&x) { return x != *it; });
res.emplace_back(*it, std::distance(it, it2));
it = it2;
}
return res;
}
Demo
If I want to use std::list and that the new elements inserted to the list will be inserted to the right position in relation to a compare function - can I do it ?
or I have to use std::sort after each insertion?
You can use:
std::set if your elements a immutable
std::map if your elements have immutable keys, but should have mutable values
std::list and looking up the insertion position
std::list with std::lower_bound:
#include <algorithm>
#include <list>
#include <iostream>
int main()
{
std::list<int> list;
int values[] = { 7, 2, 5,3, 1, 6, 4};
for(auto i : values)
list.insert(std::lower_bound(list.begin(), list.end(), i), i);
for(auto i : list)
std::cout << i;
std::cout << '\n';
}
Alternatively you may populate an entire std::vector and sort it afterwards (Note: std::sort can not operate on std::list::iterators, they do not provide random access):
#include <algorithm>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vector = { 7, 2, 5,3, 1, 6, 4};
std::sort(vector.begin(), vector.end());
for(auto i : vector)
std::cout << i;
std::cout << '\n';
}
Note: The performance of a list with manual lookup of the insertion position is the worst O(N²).
Yes you can. Try something like following, just change compare function and type if needed.
#include <list>
inline
int compare(int& a, int&b) {
return a - b;
}
template<typename T>
void insert_in_order(std::list<T>& my_list, T element, int (*compare)(T& a, T&b)) {
auto begin = my_list.begin();
auto end = my_list.end();
while ( (begin != end) &&
( compare(*begin,element) < 0 ) ) {
++begin;
}
my_list.insert(begin, element);
}
int main() {
std::list<int> my_list = { 5,3,2,1 };
my_list.sort(); //list == { 1,2,3,5}
insert_in_order<int>(my_list, 4, &compare); //list == {1,2,3,4,5}
}
You have three options:
Sort after every insertion
Find the right index and insert at that index
Use an std::set (recommended)
Example for third option:
#include <iostream>
#include <set>
int main ()
{
int myints[] = {75,23,65,42,13};
std::set<int> myset (myints,myints+5);
std::cout << "myset contains:";
for (std::set<int>::iterator it=myset.begin(); it!=myset.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
Output:
myset contains: 13 23 42 65 75
What is the most efficient and standard (C++11/14) way to find the max/min item of vector of vectors?
std::vector<std::vector<double>> some_values{{5,0,8},{3,1,9}};
the wanted max element is 9
the wanted min element is 0
Here's a multi-threaded solution that returns an iterator (or throws) to the maximum for general type T (assuming operator< is defined for T). Note the most important optimisation is to perform the inner max operations on the 'columns' to exploit C++'s column-major ordering.
#include <vector>
#include <algorithm>
template <typename T>
typename std::vector<T>::const_iterator max_element(const std::vector<std::vector<T>>& values)
{
if (values.empty()) throw std::runtime_error {"values cannot be empty"};
std::vector<std::pair<typename std::vector<T>::const_iterator, bool>> maxes(values.size());
threaded_transform(values.cbegin(), values.cend(), maxes.begin(),
[] (const auto& v) {
return std::make_pair(std::max_element(v.cbegin(), v.cend()), v.empty());
});
auto it = std::remove_if(maxes.begin(), maxes.end(), [] (auto p) { return p.second; });
if (it == maxes.begin()) throw std::runtime_error {"values cannot be empty"};
return std::max_element(maxes.begin(), it,
[] (auto lhs, auto rhs) {
return *lhs.first < *rhs.first;
})->first;
}
threaded_transform is not part of the standard library (yet), but here's an implementation you could use.
#include <vector>
#include <thread>
#include <algorithm>
#include <cstddef>
template <typename InputIterator, typename OutputIterator, typename UnaryOperation>
OutputIterator threaded_transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op, unsigned num_threads)
{
std::size_t num_values_per_threads = std::distance(first, last) / num_threads;
std::vector<std::thread> threads;
threads.reserve(num_threads);
for (int i = 1; i <= num_threads; ++i) {
if (i == num_threads) {
threads.push_back(std::thread(std::transform<InputIterator,
OutputIterator, UnaryOperation>,
first, last, result, op));
} else {
threads.push_back(std::thread(std::transform<InputIterator,
OutputIterator, UnaryOperation>,
first, first + num_values_per_threads,
result, op));
}
first += num_values_per_threads;
result += num_values_per_threads;
}
for (auto& thread : threads) thread.join();
return result;
}
template <typename InputIterator, typename OutputIterator, typename UnaryOperation>
OutputIterator threaded_transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op)
{
return threaded_transform<InputIterator, OutputIterator, UnaryOperation>(first, last, result, op, std::thread::hardware_concurrency());
}
If you used a boost::multi_array<double, 2> instead of a std::vector<std::vector<double>> it would be as simple as:
auto minmax = std::minmax_element(values.data(), values.data() + values.num_elements());
Live demo.
The plain for loop way:
T max_e = std::numeric_limits<T>::min();
for(const auto& v: vv) {
for(const auto& e: v) {
max_e = std::max(max_e, e);
}
}
You must at least look at every element, so, as Anony-mouse mentioned, complexity will be at least O(n^2).
#include <vector>
#include <limits>
#include <algorithm>
int main() {
std::vector<std::vector<double>> some_values;
double max = std::numeric_limits<double>::lowest();
for (const auto& v : some_values)
{
double current_max = *std::max_element(v.cbegin(), v.cend());
max = max < current_max ? current_max : max; // max = std::max(current_max, max);
}
}
You can do it pretty easily with Eric Niebler's range-v3 library (which obviously isn't standard yet, but hopefully will be in the not-too-distant future):
vector<vector<double>> some_values{{5,0,8},{3,1,9}};
auto joined = some_values | ranges::view::join;
auto p = std::minmax_element(joined.begin(), joined.end());
p.first is an iterator to the min element; p.second to the max.
(range-v3 does have an implementation of minmax_element, but unfortunately, it requires a ForwardRange and view::join only gives me an InputRange, so I can't use it.)
Any efficient way to calculate the maximum element in a 2-D array(or vector in your case) involves a complexity of O(n^2) irrespective of what you do, as the calculation involves a comparison between n*n elements.Best way in terms of ease of use is to use std::max_element on the vector of vectors.I will not delve into details.Here is the reference.
If you create a custom iterator to iterate over all double of your vector of vector, a simple std::minmax_element do the job
iterator is something like:
class MyIterator : public std::iterator<std::random_access_iterator_tag, double>
{
public:
MyIterator() : container(nullptr), i(0), j(0) {}
MyIterator(const std::vector<std::vector<double>>& container,
std::size_t i,
std::size_t j) : container(&container), i(i), j(j)
{
// Skip empty container
if (i < container.size() && container[i].empty())
{
j = 0;
++(*this);
}
}
MyIterator(const MyIterator& rhs) = default;
MyIterator& operator = (const MyIterator& rhs) = default;
MyIterator& operator ++() {
if (++j >= (*container)[i].size()) {
do {++i;} while (i < (*container).size() && (*container)[i].empty());
j = 0;
}
return *this;
}
MyIterator operator ++(int) { auto it = *this; ++(*this); return it; }
MyIterator& operator --() {
if (j-- == 0) {
do { --i; } while (i != 0 && (*container)[i].empty());
j = (*container)[i].size();
}
return *this;
}
MyIterator operator --(int) { auto it = *this; --(*this); return it; }
double operator *() const { return (*container)[i][j]; }
bool operator == (const MyIterator& rhs) const {
return container == rhs.container && i == rhs.i && j == rhs.j;
}
bool operator != (const MyIterator& rhs) const { return !(*this == rhs); }
private:
const std::vector<std::vector<double>>* container;
std::size_t i;
std::size_t j;
};
And usage may be
// Helper functions for begin/end
MyIterator MyIteratorBegin(const std::vector<std::vector<double>>& container)
{
return MyIterator(container, 0, 0);
}
MyIterator MyIteratorEnd(const std::vector<std::vector<double>>& container)
{
return MyIterator(container, container.size(), 0);
}
int main() {
std::vector<std::vector<double>> values = {{5,0,8}, {}, {3,1,9}};
auto b = MyIteratorBegin(values);
auto e = MyIteratorEnd(values);
auto p = std::minmax_element(b, e);
if (p.first != e) {
std::cout << "min is " << *p.first << " and max is " << *p.second << std::endl;
}
}
Live example
Using the accumulate function you could write:
#include <iostream>
#include <numeric>
#include <vector>
int main()
{
std::vector<std::vector<double>> m{ {5, 0, 8}, {3, 1, 9} };
double x = std::accumulate(m.begin(), m.end(), m[0][0],
[](double max, const std::vector<double> &v)
{
return std::max(max,
*std::max_element(v.begin(),
v.end()));
});
std::cout << x << '\n';
return 0;
}
but I'd prefer the good, old for-loop.
The example can be extended to find both the min and max values:
std::accumulate(m.begin(), m.end(),
std::make_pair(m[0][0], m[0][0]),
[](std::pair<double, double> minmax, const std::vector<double> &v)
{
auto tmp(std::minmax_element(v.begin(), v.end()));
return std::make_pair(
std::min(minmax.first, *tmp.first),
std::max(minmax.second, *tmp.second));
});
(in real code you have to handle the empty-vector case)
Unfortunately a vector of vector isn't stored contiguously in memory, so you haven't a single block containing all the values (this is one of the reasons why a vector of vector isn't a good model for a matrix).
You can take advantage of a vector of vector if it contains a lot of elements.
Since each sub-vector is autonomous, you could use std::async to fill asynchronously a vector of futures containing the max value of each sub-vector.
The simplest method would be to first have a function to determine the max/min elements of one vector, say a function called:
double getMaxInVector(const vector<double>& someVec){}
Passing by reference (for reading purposes only) in this case will be a lot more time and space efficient (you don't want your function copying an entire vector). Thus in your function to determine max/min element of a vector of vectors, you would have a nested loop, such as:
for(size_t x= 0; x < some_values.size(); x++){
for(size_t y = 0; y < x.size(); y++){
// y represents the vectors inside the vector of course
// current max/min = getMax(y)
// update max/min after inner loop finishes and x increments
// by comparing it with previous max/min
The problem with the above solution is its inefficiency. From my knowledge, this algorithm will generally run on O(n^2log(n)) efficiency, which is quite unimpressive. But of course, it is still a solution. Although there might be standard algorithms that can find the max/min of a vector for you, it's always more accomplishing to write your own, and using the given will usually do nothing in terms of improving efficiency because the algorithm will generally be the same (for small functions that determine max/min). In fact, theoretically, standard functions would run marginally slower since those functions are templates which have to determine the type it is dealing with at run-time.
Lets say we have a vector named some_values, as shown below
7 4 2 0
4 8 10 8
3 6 7 6
3 9 19* 14
define a one-dimensional vector as shown below
vector<int> oneDimVector;
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
oneDimVector.push_back(some_values[i][j]);
}
}
Then find out a maximum/minimum element in that one-dimensional vector as shown below
vector<int>::iterator maxElement = max_element(oneDimVector.begin(),oneDimVector.end());
vector<int>::iterator minElement = min_element(oneDimVector.begin(),oneDimVector.end());
Now you get the max/min elements as below
cout << "Max element is " << *maxElement << endl;
cout << "Min element is " << *minElement << endl;
vector<vector<int>> vv = { vector<int>{10,12,43,58}, vector<int>{10,14,23,18}, vector<int>{28,47,12,90} };
vector<vector<int>> vv1 = { vector<int>{22,24,43,58}, vector<int>{56,17,23,18}, vector<int>{11,12,12,90} };
int matrix1_elem_sum=0;
int matrix2_elem_sum = 0;
for (size_t i = 0; i < vv.size(); i++)
{
matrix1_elem_sum += std::accumulate(vv[i].begin(), vv[i].end(), 0);
matrix2_elem_sum += std::accumulate(vv1[i].begin(), vv1[i].end(), 0);
}
cout << matrix1_elem_sum <<endl;
cout << matrix2_elem_sum << endl;
int summ = matrix1_elem_sum + matrix2_elem_sum;
cout << summ << endl;
or optimazed variant:
vector<vector<int>> vv = { vector<int>{10,12,43,58}, vector<int>{10,14,23,18}, vector<int>{28,47,12,90} };
vector<vector<int>> vv1 = { vector<int>{22,24,43,58}, vector<int>{56,17,23,18}, vector<int>{11,12,12,90} };
int summ=0;
int matrix2_elem_sum = 0;
for (size_t i = 0; i < vv.size(); i++)
{
summ += std::accumulate(vv[i].begin(), vv[i].end(), 0)+ std::accumulate(vv1[i].begin(), vv1[i].end(), 0);
}
cout << summ << endl;
}
Is it possible to iterate a vector from the end to the beginning?
for (vector<my_class>::iterator i = my_vector.end();
i != my_vector.begin(); /* ?! */ ) {
}
Or is that only possible with something like that:
for (int i = my_vector.size() - 1; i >= 0; --i) {
}
One way is:
for (vector<my_class>::reverse_iterator i = my_vector.rbegin();
i != my_vector.rend(); ++i ) {
}
rbegin()/rend() were especially designed for that purpose. (And yes, incrementing a reverse_interator moves it backward.)
Now, in theory, your method (using begin()/end() & --i) would work, std::vector's iterator being bidirectional, but remember, end() isn't the last element — it's one beyond the last element, so you'd have to decrement first, and you are done when you reach begin() — but you still have to do your processing.
vector<my_class>::iterator i = my_vector.end();
while (i != my_vector.begin())
{
--i;
/*do stuff */
}
UPDATE: I was apparently too aggressive in re-writing the for() loop into a while() loop. (The important part is that the --i is at the beginning.)
If you have C++11 you can make use of auto.
for (auto it = my_vector.rbegin(); it != my_vector.rend(); ++it)
{
}
Starting with c++20, you can use a std::ranges::reverse_view and a range-based for-loop:
#include<ranges>
#include<vector>
#include<iostream>
using namespace std::ranges;
std::vector<int> const vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(auto& i : views::reverse(vec)) {
std::cout << i << ",";
}
Or even
for(auto& i : vec | views::reverse)
Unfortunately, at the time of writing (Jan 2020) no major compiler implements the ranges library, but you can resort to Eric Niebler's ranges-v3:
#include <iostream>
#include <vector>
#include "range/v3/all.hpp"
int main() {
using namespace ranges;
std::vector<int> const vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(auto& i : views::reverse(vec)) {
std::cout << i << ",";
}
return 0;
}
The well-established "pattern" for reverse-iterating through closed-open ranges looks as follows
// Iterate over [begin, end) range in reverse
for (iterator = end; iterator-- != begin; ) {
// Process `*iterator`
}
or, if you prefer,
// Iterate over [begin, end) range in reverse
for (iterator = end; iterator != begin; ) {
--iterator;
// Process `*iterator`
}
This pattern is useful, for example, for reverse-indexing an array using an unsigned index
int array[N];
...
// Iterate over [0, N) range in reverse
for (unsigned i = N; i-- != 0; ) {
array[i]; // <- process it
}
(People unfamiliar with this pattern often insist on using signed integer types for array indexing specifically because they incorrectly believe that unsigned types are somehow "unusable" for reverse indexing)
It can be used for iterating over an array using a "sliding pointer" technique
// Iterate over [array, array + N) range in reverse
for (int *p = array + N; p-- != array; ) {
*p; // <- process it
}
or it can be used for reverse-iteration over a vector using an ordinary (not reverse) iterator
for (vector<my_class>::iterator i = my_vector.end(); i-- != my_vector.begin(); ) {
*i; // <- process it
}
User rend() / rbegin() iterators:
for (vector<myclass>::reverse_iterator it = myvector.rbegin(); it != myvector.rend(); it++)
template<class It>
std::reverse_iterator<It> reversed( It it ) {
return std::reverse_iterator<It>(std::forward<It>(it));
}
Then:
for( auto rit = reversed(data.end()); rit != reversed(data.begin()); ++rit ) {
std::cout << *rit;
Alternatively in C++14 just do:
for( auto rit = std::rbegin(data); rit != std::rend(data); ++rit ) {
std::cout << *rit;
In C++03/11 most standard containers have a .rbegin() and .rend() method as well.
Finally, you can write the range adapter backwards as follows:
namespace adl_aux {
using std::begin; using std::end;
template<class C>
decltype( begin( std::declval<C>() ) ) adl_begin( C&& c ) {
return begin(std::forward<C>(c));
}
template<class C>
decltype( end( std::declval<C>() ) ) adl_end( C&& c ) {
return end(std::forward<C>(c));
}
}
template<class It>
struct simple_range {
It b_, e_;
simple_range():b_(),e_(){}
It begin() const { return b_; }
It end() const { return e_; }
simple_range( It b, It e ):b_(b), e_(e) {}
template<class OtherRange>
simple_range( OtherRange&& o ):
simple_range(adl_aux::adl_begin(o), adl_aux::adl_end(o))
{}
// explicit defaults:
simple_range( simple_range const& o ) = default;
simple_range( simple_range && o ) = default;
simple_range& operator=( simple_range const& o ) = default;
simple_range& operator=( simple_range && o ) = default;
};
template<class C>
simple_range< decltype( reversed( adl_aux::adl_begin( std::declval<C&>() ) ) ) >
backwards( C&& c ) {
return { reversed( adl_aux::adl_end(c) ), reversed( adl_aux::adl_begin(c) ) };
}
and now you can do this:
for (auto&& x : backwards(ctnr))
std::cout << x;
which I think is quite pretty.
Use reverse iterators and loop from rbegin() to rend()
I like the backwards iterator at the end of Yakk - Adam Nevraumont's answer, but it seemed complicated for what I needed, so I wrote this:
template <class T>
class backwards {
T& _obj;
public:
backwards(T &obj) : _obj(obj) {}
auto begin() {return _obj.rbegin();}
auto end() {return _obj.rend();}
};
I'm able to take a normal iterator like this:
for (auto &elem : vec) {
// ... my useful code
}
and change it to this to iterate in reverse:
for (auto &elem : backwards(vec)) {
// ... my useful code
}
If you can use The Boost Library, there is the Boost.Range that provides the reverse range adapter by including:
#include <boost/range/adaptor/reversed.hpp>
Then, in combination with a C++11's range-for loop, you can just write the following:
for (auto& elem: boost::adaptors::reverse(my_vector)) {
// ...
}
Since this code is briefer than the one using the iterator pair, it may be more readable and less prone to errors as there are fewer details to pay attention to.
Here's a super simple implementation that allows use of the for each construct and relies only on C++14 std library:
namespace Details {
// simple storage of a begin and end iterator
template<class T>
struct iterator_range
{
T beginning, ending;
iterator_range(T beginning, T ending) : beginning(beginning), ending(ending) {}
T begin() const { return beginning; }
T end() const { return ending; }
};
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usage:
// for (auto e : backwards(collection))
template<class T>
auto backwards(T & collection)
{
using namespace std;
return Details::iterator_range(rbegin(collection), rend(collection));
}
This works with things that supply an rbegin() and rend(), as well as with static arrays.
std::vector<int> collection{ 5, 9, 15, 22 };
for (auto e : backwards(collection))
;
long values[] = { 3, 6, 9, 12 };
for (auto e : backwards(values))
;
can try this one (only for --i):
std:vector<int> vec = {1, 2, 3};
size_t i{ vec.size() - 1 };
while (i < size_t(-1))
{
auto& el = vec[i];
--i;
}
use this code
//print the vector element in reverse order by normal iterator.
cout <<"print the vector element in reverse order by normal iterator." <<endl;
vector<string>::iterator iter=vec.end();
--iter;
while (iter != vec.begin())
{
cout << *iter << " ";
--iter;
}
As I don't want to introduce alien-like new C++ syntax, and I simply want to build up on existing primitives, the below snippets seems to work:
#include <vector>
#include <iostream>
int main (int argc,char *argv[])
{
std::vector<int> arr{1,2,3,4,5};
std::vector<int>::iterator it;
// iterate forward
for (it = arr.begin(); it != arr.end(); it++) {
std::cout << *it << " ";
}
std::cout << "\n************\n";
if (arr.size() > 0) {
// iterate backward, simple Joe version
it = arr.end() - 1;
while (it != arr.begin()) {
std::cout << *it << " ";
it--;
}
std::cout << *it << " ";
}
// iterate backwards, the C++ way
std::vector<int>::reverse_iterator rit;
for (rit = arr.rbegin(); rit != arr.rend(); rit++) {
std::cout << *rit << " ";
}
return 0;
}