Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to merely simulate the Matlab "unique" function in c++

Tags:

c++

matlab

I have the following vector, v = [ 9 2 9 5] and the unique elements c = [2 5 9] of it in a ascending order. I wish to extract the vector u = [3 1 3 2]. The u vector contains the indexes of the unique elements in vector c so as to reconstruct the vector v.

My thoughts was to iterate though v and with the help of a hash table constructed based on the unique values of c to obtain the index values. Is this meaningful? If yes, could you please some one suggest a way in c++? An other suggestions are highly appreciated (I am interested in efficient implementations because the v and c matrix are big enough).

Best regards, Thoth

like image 695
Thoth Avatar asked Apr 13 '14 20:04

Thoth


1 Answers

indices in C++ start from 0. So it would be more correctly to write

u = { 2, 0, 2, 1 };

You can use standard algorithms to do the task. For example (here I suppose that vector c is already built some way)

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

int main()
{ 
   std::vector<int> v = { 9, 2, 9, 5 };
   std::vector<int> c = { 2, 5, 9 };

   std::vector<int> u;
   u.reserve( v.size() );

   std::transform( v.begin(), v.end(), std::back_inserter( u ),
                   [&]( int x )
                   {
                      return ( std::distance( c.begin(), 
                               std::lower_bound( c.begin(), c.end(), x ) ) );
                   } );

   for ( int x : u ) std::cout << x << ' ';
   std::cout << std::endl;
}

You can use std::set<int> instead of std::vector<int> if you need to get unique values from vector v. For example

#include <iostream>
#include <vector>
#include <set>
#include <iterator>
#include <algorithm>

int main()
{ 
   std::vector<int> v = { 9, 2, 9, 5 };
   std::set<int> c( v.begin(), v.end() );

   std::vector<int> u;
   u.reserve( v.size() );

   std::transform( v.begin(), v.end(), std::back_inserter( u ),
                   [&]( int x )
                   {
                      return ( std::distance( c.begin(), c.find( x ) ) );
                   } );

   for ( int x : u ) std::cout << x << ' ';
   std::cout << std::endl;
}
like image 183
Vlad from Moscow Avatar answered Oct 11 '22 00:10

Vlad from Moscow