Home > OS >  c implement of array broadcast
c implement of array broadcast

Time:02-23

In python language, we can use A[A!=0]=-10 to trans all the non-zero value in A to -10. How can I implement this function in C language or is here any similar function in 3rd party?

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    Mat A(3, 3, CV_16SC1);
    for (int i = 0; i < 3; i  )
    {
        for (int j = 0; j < 3; j  )
        {
            A.at<short>(i, j) = i   j;
        }
    }
    for (auto& value : A) if (value != 2) value = -10;
}

CodePudding user response:

There is std::ranges::replace in C 20:

std::vector<int> values = {1,2,3,1,2,5,3,165};
std::ranges::replace(values, 3, 999);

And, similarly, std::ranges::replace_if in C 20:

std::vector<int> values = {1,2,0,1,0,5,3,165};
std::ranges::replace_if(values, [](int a) { return a != 0;}, -10);

You can see it in compiler explorer

It is also possible to use std::not_equal_to with std::bind_front instead of the lambda, if you prefer it that way, values = {1,2,0,1,0,5,3,165}; print("Before: ", values); std::ranges::replace_if(values, [](int a) { return a !!= 0; }, -10); print("replaced with lambda: ", values); values = {1,2,0,1,0,5,3,165}; print("Before: ", values); std::ranges::replace_if(values, std::bind_front(std::not_equal_to{}, 0), -20); print("replaced with std::bind_front: ", values); }'),l:'5',n:'0',o:'C++ source #1',t:'0')),k:48.1191222570533,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:gsnapshot,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'0',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:2,lang:c++,libs:!(),options:'--std=c++20 -O3',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'x86-64 gcc (trunk) (C++, Editor #1, Compiler #2)',t:'0')),k:25,l:'4',m:43.87755102040816,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(compiler:2,editor:1,fontScale:14,fontUsePx:'0',tree:'1',wrap:'1'),l:'5',n:'0',o:'Output of x86-64 gcc (trunk) (Compiler #2)',t:'0')),header:(),l:'4',m:56.122448979591844,n:'0',o:'',s:0,t:'0')),k:51.880877742946716,l:'3',n:'0',o:'',t:'0')),l:'2',n:'0',o:'',t:'0')),version:4" rel="nofollow noreferrer">like this

Edit: here is the bind_front code (from the above link):

std::ranges::replace_if(values, std::bind_front(std::not_equal_to{}, 0),  -20);

CodePudding user response:

In STL container there is a function that has similar behavior. For example:

#include <vector>
#include <algorithm>

int main() {
    using namespace std;
    vector<int> example_vector{0,1,4,1,5};
    for_each(example_vector.begin(), example_vector.end(), [](auto& a) {  if (a != 0)a = -10; });
}

Although the syntax seems not simple like python, it is optimized, and may be parallelized by execution policy.

CodePudding user response:

Range-based for loops will not work since the cv::Mat::begin() is a member function template. You'll have to use begin<mat_type>() and end<mat_type>().

Example:

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

#include <algorithm>
#include <iostream>
#include <iterator>

int main() {
    cv::Mat A(3, 3, CV_16SC1);

    using mtype = short;                              // convenience typedef

    for(int i = 0; i < 3; i  ) {
        for(int j = 0; j < 3; j  ) {
            A.at<mtype>(i, j) = i   j;                // using mtype
        }
    }

    // using mtype:
    for(auto it = A.begin<mtype>(); it != A.end<mtype>();   it) {
        if(*it != 2) *it = -10;
    }

    // print result:
    std::copy(A.begin<mtype>(), A.end<mtype>(),
              std::ostream_iterator<mtype>(std::cout, "\n"));
}

Or using the std::replace_if algorithm to replace all non 2's with -10:

    std::replace_if(A.begin<mtype>(), A.end<mtype>(),  // using mtype
        [](auto& value) { return value != 2; }, -10);

Output:

-10
-10
2
-10
2
-10
2
-10
-10
  • Related