I have some vector vec and i want to obtain a new "expression" vec2 by copying values along dimension of vector
Eigen::VectorXf vec(5);
vec << 1, 2, 3, 4, 5;
const auto vec2 = vec.someAwesomeEigenMagic<3>();
//vec2 should contains (1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5)^T
//Not (1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5)^T
Of course i can create such vector manually or by using replicate + vectorization by Eigen::Map:
MatrixXf tmp = vec.replicate(1, 3).transpose();
const Map<VectorXf> vec2(tmp.data(), vec.rows() * 3, 1);
But i want vec2 to be some kind of "eigen template expression" without allication (vec can be quite big and i will call this routine quite often) and immediate computing of values. (vec contains per vertex weights and i want to use it for weighted least squares)
I thought about kronecker product trick with vector of ones, but i'm not sure is it optimized for product by ones. Also i prefer to avoid unsupported module
PS Sorry for my English
Using the devel branch you can use LinSpaced to generate the sequence of indices and then index the input vector:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
VectorXf vec(5);
vec << 1, 2, 3, 4, 5;
auto vecrep = vec(ArrayXi::LinSpaced(5*3,0,4));
cout << vecrep.transpose() << endl;
}
you can then wrap the key line within a free function returning auto, in c++14:
template<typename XprType>
auto magic_rep(const XprType &xpr, Index K) {
return xpr(Eigen::ArrayXi::LinSpaced(xpr.size()*K,0,xpr.size()-1));
}
and in main:
cout << magic_rep(vec,3).transpose() << endl;
Related
This question already has answers here:
std::remove_if - lambda, not removing anything from the collection
(4 answers)
Closed 1 year ago.
I am trying to remove elements from a vector of ints using std::remove_if, but am not getting the required output.
Initial vector members: {0, 1, 2, 1, 3, 1, 4, 5, 1, 6, 1, 7, 1, 8, 1, 9}
Required Output: {0, 2, 3, 4, 5, 6, 7, 8, 9}
Actual Output: {0, 2, 3, 4, 5, 6, 7, 8, 9, 6, 1, 7, 1, 8, 1, 9}
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
class Equal
{
public:
Equal(int a): a_(a){}
bool operator()(int b)
{
return a_ == b;
}
private:
int a_;
};
int main()
{
std::vector<int> vi{0, 1, 2, 1, 3, 1, 4, 5, 1, 6, 1, 7, 1, 8, 1, 9};
std::cout << std::endl;
std::remove_if(vi.begin(), vi.end(), Equal(1));
for (const auto &i : vi) std::cout << i << " ";
return 0;
}
There are just as many elements in the vector before and after the call to
std::remove_if:
Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range.
... and std::remove_if returns an iterator to the start of the "removed" elements and you can use that iterator to actually erase the elements: See Erase–remove idiom
vi.erase(
std::remove_if(vi.begin(), vi.end(), Equal(1)), // returns iterator
vi.end() // erase to the end
);
Demo
Also note that std::vector got a new specialized function in C++20 that does both things, namely std::erase_if.
Example:
std::erase_if(vi, Equal(1));
I'm currently trying to find the minimum element of a 2D vector. I'm trying to practice using C++11 lambda functions and figured this might be good practice, but can't seem to get it compiling.
I'm aware that I could do the following:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
int result = std::numeric_limits<int>::max();
for(const auto& row : matrix)
{
int minElemInRow = *std::min_element(row.begin(), row.end());
result = std::min(result , minElemInRow);
}
return result;
but was wondering if the same could be done with a lambda function. Currently, this is my best attempt:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
return *std::min_element(matrix.begin(), matrix.end(),
[](const auto& row)
{
return *std::min_element(row.begin(), row.end());
});
I get the error: error C2672: 'operator __surrogate_func': no matching overloaded function found
How I feel it should be working is that the outer min_element will pass in a row at a time (which is just a reference to a vector), from which I can return the smallest, which will then be compared against other rows.
I thought that the problem might be that the lambda would be receiving an iterator to a vector of ints rather than a reference to the vector of ints, but dereferencing doesn't seem to be helping.
Is there a better way to be doing what I'm trying to do?
#assembly_wizard pointed out that min_element wants a predicate which can compare two of the item passed it. That is two rows. This leads to the following code:
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
auto i = std::min_element(matrix.begin(), matrix.end(),
[](const auto& lhs, const auto& rhs)
{
return *std::min_element(lhs.begin(), lhs.end()) <
*std::min_element(rhs.begin(), rhs.end());
});
This will find the row with the smallest element. Though I can make that work by wrapping it in yet another std::min_element, that's getting way more complex than to be remotely helpful. If anyone has a better suggestion, I'd love to hear it!
I've compiled a working version that does what I've mentioned in the comments:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
std::vector<int> row_minimums(matrix.size());
std::transform(matrix.begin(), matrix.end(), row_minimums.begin(), [](const auto& row) {
return *std::min_element(row.begin(), row.end());
});
auto i = *std::min_element(row_minimums.begin(), row_minimums.end());
std::cout << "Minimum element is: " << i << std::endl;
}
See it in action on godbolt
This will take the minimum of each row separately, so we get row_minimums which is a vector of ints, and then it takes the minimum of these to get the final result between all the rows.
The only thing making this code worse than the for loop version, is that it keeps all of the row_minimums in memory at once, before running min_element on them. Unfortunately I don't know of a way to do this simultaneously, but I'm not the greatest STL expect, so maybe there is a way.
Other options you might consider is first concatenating the 2D matrix into a 1D vector and then using min_element on it, or the option you've included in your edit where you call min_element 3 times.
Also, this SO answer seems to have interesting info regarding solutions using the boost library which might be better, but I'm not sure exactly what they are.
Just a little simpler:
With std::for_each you iterate over each vector in matrix, and obtain the minimum element of them. As min is captured by reference, you get the min of all of them.
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<std::vector<int>> matrix = {
{1, 2, 3, 4, 5 },
{6, 7, 8, 9, 10 },
{5, 6, 8, 1, 12 },
{1, 7, 2, 4, 18 },
};
int min = std::numeric_limits<int>::max();
std::for_each(matrix.begin(), matrix.end(),
[&min](const auto& v)
{
min = std::min(*min_element(v.begin(), v.end()), min);
}
);
std::cout << "Minimum element is: " << min << std::endl;
}
I have a column-based(each column is a feature) large array(around 100M) which has dimensions of 75000(fixed)*number of samples
This is data vector:
std::vector<float> features;
I have used this code to calculate mean:
cv::Mat data(FEATURE_SIZE, features.size()/FEATURE_SIZE, CV_32F, &features[0]);
cv::reduce(data,dataMeans,1,CV_REDUCE_AVG);
FEATURE_SIZE is 75000 and features is a float vector which has all the data.
In order to calculate mean shift I used this:
data -= cv::repeat(dataMeans,1,features.size()/FEATURE_SIZE);
Which I think tries to create an array of same size with my features array and therefore giving me a bad allocation exception.
I just need that array to be mean differentiated. Is there any way to do it without copying, on the same memory location?
First, you messed up columns and rows.
Here a correct way to do what you want:
#define FEATURES_SIZE 3
int main()
{
vector<float> features = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Mat1f data(features.size() / FEATURES_SIZE, FEATURES_SIZE, &features[0]);
Mat dataMeans;
cv::reduce(data, dataMeans, 1, CV_REDUCE_AVG);
data -= repeat(dataMeans, 1, FEATURES_SIZE);
}
However, probably you can't use opencv matrices with your dimensions.
You can instead use std functions:
// other includes
#include <algorithm>
#include <numeric>
#include <functional>
#define FEATURES_SIZE 3
int main()
{
vector<float> features = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
for(size_t i = 0; i<features.size(); i+= FEATURES_SIZE)
{
float cumsum = accumulate(features.begin() + i, features.begin() + i + FEATURES_SIZE, 0.f);
float avg = cumsum / FEATURES_SIZE;
transform(features.begin() + i, features.begin() + i + FEATURES_SIZE, features.begin() + i, bind2nd(std::minus<float>(), avg));
}
}
I don't know if this is the "minimum number of copies" optimal solution. Try with your large arrays and check if it is a problem.
Note: using namespace std; and using namespace cv used in my examples for brevity.
Hope it helps!
vector<int> data = {3, 1, 5, 3, 3, 8, 7, 3, 2};
std::nth_element(data.begin(), data.begin() + median, data.end());
Will this always result in:
data = {less, less, 3, 3, 3, 3, larger, larger, larger} ?
Or would a other possible outcome be:
data = {3, less, less, 3, 3, 3, larger, larger, larger} ?
I've tried it multiple times on my machine wich resulted in the nth values always being contiguous. But that's not proof ;).
What it's for:
I want to building a unique Kdtree but I have duplicates in my vector. Currently I'm using nth_element to find the median value. The issue is to select a unique/reconstructible median, without having to traverse the vector again. If the median values were contiguous I could choose a unique median, without much traversing.
No. The documentation does not specify such behavior, and with a few minutes of experimentation, it was pretty easy to find a test case where the dupes weren't contiguous on ideone:
#include <iostream>
#include <algorithm>
int main() {
int a[] = {2, 1, 2, 3, 4};
std::nth_element(a, a+2, a+5);
std::cout << a[1];
return 0;
}
Output:
1
If the dupes were contiguous, that output would have been 2.
I have just tried several not-so-simple examples, and on the third got non-contiguous output.
Program
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> a = {1, 3, 3, 2, 1, 3, 5, 5, 5, 5};
std::nth_element(a.begin(), a.begin() + 5, a.end());
for(auto v: a) std::cout << v << " ";
std::cout << std::endl;
}
with gcc 4.8.1 under Linux, with std=c++11, gives me output
3 1 1 2 3 3 5 5 5 5
while the n-th element is 3.
So no, the elements are not always contiguous.
I also think that even a simpler way, with no thinking of a good test case, was just generating long random arrays with many duplicate elements and checking whether it holds. I think it will break on the first or second attempt.
I'm beginning programming, so sorry for my lack of knowledge.
How can I set elements in vector in a specific order? I would like to swap elements in the way that there won't be same elements next to each other.
For example vector contains:
{1, 2, 2, 2, 3, 3, 4, 4, 4}
and I'd like it to be like:
{1, 2, 4, 3, 4, 2, 3, 2, 4}
Thanks for help.
edit:
Hello again, I found not the best solution, maybe you can take a look and correct it?
map<unsigned,unsigned> Map;
for(vector<unsigned>::iterator i=V.begin();i!=V.end();++i)
{
map<unsigned,unsigned>::iterator f=Map.find(*i);
if(f==Map.end()) Map[*i]=1;
else ++f->second;
}
for(bool more=true;more;)
{
more=false;
for(map<unsigned,unsigned>::iterator i=Map.begin();i!=Map.end();++i)
{
if(i->second)
{
--i->second;
cout<<i->first<<", ";
more=true;
}
}
}
Now, for { 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 } it gives me { 1, 2, 3, 4, 2, 3, 4, 2, 4, 4, 4, 4 } instead of e.g { 4, 1, 4, 2, 4, 3, 4, 2, 4, 3, 4, 2 }. How can it be done? Thanks
credits: _13th_Dragon
Count the occurrences of each value.
Starting with the most-frequent value, alternate it with less-frequent values.
In order to achieve (1), one can simply use std::map<V, unsigned>. However, for the second, one needs an ordered set of std::pair<V, unsigned int>, ordered by the second value. Since we want to keep track of how many times we need to use a given value, the second value cannot be constant. Also, we don't want to change the order if we happen to decrease the count of a given value much. All in all we get
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
// In the pair, first is the original value, while
// second is the number occurrences of that value.
typedef std::pair<int, unsigned> value_counter;
int main(){
std::vector<int> sequence = { 0, 1, 3, 3, 4, 1, 2, 2, 2, 2 , 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 };
std::map<int, unsigned> count;
for( auto i : sequence){
count[i]++;
}
std::vector<value_counter> store( count.size() );
std::copy(count.begin(), count.end(), store.begin());
// Sort by the second value
std::sort(store.begin(), store.end(),
[](const value_counter& a, const value_counter& b){
return a.second > b.second;
});
std::vector<int> result;
// We need two indices, one for the current value
// and the other one for the alternative
for(unsigned i = 0, j = 1; i < store.size(); ++i){
while(store[i].second > 0){
result.push_back(store[i].first);
store[i].second--;
if(store[i].second == 0)
continue;
if( j <= i)
j = i + 1;
while(j < store.size() && store[j].second == 0)
++j;
if(j >= store.size()){
std::cerr << "Not enough elements for filling!" << std::endl;
return 1;
}
else {
result.push_back(store[j].first);
store[j].second--;
}
}
}
for( auto r : result){
std::cout << r << " ";
}
}
Instead of using a typedef you could create an alternative counter which has better names than first and second, but that makes copying from the map a little bit more verbose.