Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. ATL / WTL / STL
  4. unique problem

unique problem

Scheduled Pinned Locked Moved ATL / WTL / STL
helpquestionc++dotnetgraphics
10 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    s196675m
    wrote on last edited by
    #1

    HI I am new to this STL form. I have a simple question, unique does not work as expected. Here is my test code

    			int iList\[4\] = {0};
    			iList\[0\] = -131;
    			iList\[1\] = -131;
    			iList\[2\] = -343455555;
    			iList\[3\] = -131;
    
    			vector<int> iNeighborList(iList, iList + 4);
    			vector<int>::iterator it;
    			
    			it = unique(iNeighborList.begin(), iNeighborList.end());
    
    			iNeighborList.resize(it - iNeighborList.begin());
    

    // At this point
    //expected elements of iNeighborList are -131, -343455555
    // but actual element I got are -131,-343455555, -131
    // Why third element apprear?

    			it = remove(iNeighborList.begin(),iNeighborList.end(),-343455555); 
    			iNeighborList.resize(it - iNeighborList.begin());
    
    			int isiz = iNeighborList.size();
    

    I am using VS2005 to compile it using Pure MSIL (/clr:pure) switch. Can anybody help me why I am getting uncexppected result. Thank you

    S S S 3 Replies Last reply
    0
    • S s196675m

      HI I am new to this STL form. I have a simple question, unique does not work as expected. Here is my test code

      			int iList\[4\] = {0};
      			iList\[0\] = -131;
      			iList\[1\] = -131;
      			iList\[2\] = -343455555;
      			iList\[3\] = -131;
      
      			vector<int> iNeighborList(iList, iList + 4);
      			vector<int>::iterator it;
      			
      			it = unique(iNeighborList.begin(), iNeighborList.end());
      
      			iNeighborList.resize(it - iNeighborList.begin());
      

      // At this point
      //expected elements of iNeighborList are -131, -343455555
      // but actual element I got are -131,-343455555, -131
      // Why third element apprear?

      			it = remove(iNeighborList.begin(),iNeighborList.end(),-343455555); 
      			iNeighborList.resize(it - iNeighborList.begin());
      
      			int isiz = iNeighborList.size();
      

      I am using VS2005 to compile it using Pure MSIL (/clr:pure) switch. Can anybody help me why I am getting uncexppected result. Thank you

      S Offline
      S Offline
      s196675m
      wrote on last edited by
      #2

      Hi Is there anybody know, what mistake I made in the code . Thank you

      1 Reply Last reply
      0
      • S s196675m

        HI I am new to this STL form. I have a simple question, unique does not work as expected. Here is my test code

        			int iList\[4\] = {0};
        			iList\[0\] = -131;
        			iList\[1\] = -131;
        			iList\[2\] = -343455555;
        			iList\[3\] = -131;
        
        			vector<int> iNeighborList(iList, iList + 4);
        			vector<int>::iterator it;
        			
        			it = unique(iNeighborList.begin(), iNeighborList.end());
        
        			iNeighborList.resize(it - iNeighborList.begin());
        

        // At this point
        //expected elements of iNeighborList are -131, -343455555
        // but actual element I got are -131,-343455555, -131
        // Why third element apprear?

        			it = remove(iNeighborList.begin(),iNeighborList.end(),-343455555); 
        			iNeighborList.resize(it - iNeighborList.begin());
        
        			int isiz = iNeighborList.size();
        

        I am using VS2005 to compile it using Pure MSIL (/clr:pure) switch. Can anybody help me why I am getting uncexppected result. Thank you

        S Offline
        S Offline
        Stuart Dootson
        wrote on last edited by
        #3

        Your problem is that your expectation of what unique does is incorrect. In the MSDN Documentation for Visual Studio 2008 (and the C++ Standard says the same, but in slightly different language), it says:

        Removes duplicate elements that are adjacent to each other in a specified range.

        Only the first two elements of your array are of equal value and adjacent to each other.

        S 1 Reply Last reply
        0
        • S Stuart Dootson

          Your problem is that your expectation of what unique does is incorrect. In the MSDN Documentation for Visual Studio 2008 (and the C++ Standard says the same, but in slightly different language), it says:

          Removes duplicate elements that are adjacent to each other in a specified range.

          Only the first two elements of your array are of equal value and adjacent to each other.

          S Offline
          S Offline
          s196675m
          wrote on last edited by
          #4

          Hi Thank you for your good point. Is there any function which can find unique elements in an array vecor even though unique elements may not be adjacent.

          S 1 Reply Last reply
          0
          • S s196675m

            Hi Thank you for your good point. Is there any function which can find unique elements in an array vecor even though unique elements may not be adjacent.

            S Offline
            S Offline
            Stuart Dootson
            wrote on last edited by
            #5

            If the order of elements is unimportant, sort the vector (with std::sort) before using unique. Otherwise, try something like:

            #include <set>
            #include <vector>
            #include <iostream>
            #include <iterator>
            
            struct Finder : std::unary_function<bool, int>
            {
              Finder(std::set<int>& s) : s_(s) {}
              bool operator()(int i) const
              { 
                if (s_.count(i)==0)
                {
                  s_.insert(i);
                  return false;
                }
                else
                {
                  return true;
                }
              }
              std::set<int>& s_;
            };
            
            int main(int, char**)
            {
              std::vector<int> data;
              data.push_back(1);
              data.push_back(3);
              data.push_back(2);
              data.push_back(1);
              data.push_back(5);
              data.push_back(1);
            
              // Show the vector
              std::copy(data.begin(), data.end(), std::ostream_iterator<int>(std::cout, ", ")); std::cout << std::endl;
              
              // Use Finder and a set to remove items if we've seen them before in the vector
              std::set<int> uniqueItems;
              data.erase(std::remove_if(data.begin(), data.end(), Finder(uniqueItems)), data.end());
            
              // Show the vector with duplicates removed
              std::copy(data.begin(), data.end(), std::ostream_iterator<int>(std::cout, ", ")); std::cout << std::endl;
              return 0;
            }
            

            It's not too pretty, but should work OK. And if you parameterise Finder, you can re-use if you need to do it again

            S S 2 Replies Last reply
            0
            • S Stuart Dootson

              If the order of elements is unimportant, sort the vector (with std::sort) before using unique. Otherwise, try something like:

              #include <set>
              #include <vector>
              #include <iostream>
              #include <iterator>
              
              struct Finder : std::unary_function<bool, int>
              {
                Finder(std::set<int>& s) : s_(s) {}
                bool operator()(int i) const
                { 
                  if (s_.count(i)==0)
                  {
                    s_.insert(i);
                    return false;
                  }
                  else
                  {
                    return true;
                  }
                }
                std::set<int>& s_;
              };
              
              int main(int, char**)
              {
                std::vector<int> data;
                data.push_back(1);
                data.push_back(3);
                data.push_back(2);
                data.push_back(1);
                data.push_back(5);
                data.push_back(1);
              
                // Show the vector
                std::copy(data.begin(), data.end(), std::ostream_iterator<int>(std::cout, ", ")); std::cout << std::endl;
                
                // Use Finder and a set to remove items if we've seen them before in the vector
                std::set<int> uniqueItems;
                data.erase(std::remove_if(data.begin(), data.end(), Finder(uniqueItems)), data.end());
              
                // Show the vector with duplicates removed
                std::copy(data.begin(), data.end(), std::ostream_iterator<int>(std::cout, ", ")); std::cout << std::endl;
                return 0;
              }
              

              It's not too pretty, but should work OK. And if you parameterise Finder, you can re-use if you need to do it again

              S Offline
              S Offline
              s196675m
              wrote on last edited by
              #6

              Thanks

              1 Reply Last reply
              0
              • S Stuart Dootson

                If the order of elements is unimportant, sort the vector (with std::sort) before using unique. Otherwise, try something like:

                #include <set>
                #include <vector>
                #include <iostream>
                #include <iterator>
                
                struct Finder : std::unary_function<bool, int>
                {
                  Finder(std::set<int>& s) : s_(s) {}
                  bool operator()(int i) const
                  { 
                    if (s_.count(i)==0)
                    {
                      s_.insert(i);
                      return false;
                    }
                    else
                    {
                      return true;
                    }
                  }
                  std::set<int>& s_;
                };
                
                int main(int, char**)
                {
                  std::vector<int> data;
                  data.push_back(1);
                  data.push_back(3);
                  data.push_back(2);
                  data.push_back(1);
                  data.push_back(5);
                  data.push_back(1);
                
                  // Show the vector
                  std::copy(data.begin(), data.end(), std::ostream_iterator<int>(std::cout, ", ")); std::cout << std::endl;
                  
                  // Use Finder and a set to remove items if we've seen them before in the vector
                  std::set<int> uniqueItems;
                  data.erase(std::remove_if(data.begin(), data.end(), Finder(uniqueItems)), data.end());
                
                  // Show the vector with duplicates removed
                  std::copy(data.begin(), data.end(), std::ostream_iterator<int>(std::cout, ", ")); std::cout << std::endl;
                  return 0;
                }
                

                It's not too pretty, but should work OK. And if you parameterise Finder, you can re-use if you need to do it again

                S Offline
                S Offline
                Stephen Hewitt
                wrote on last edited by
                #7

                The definition of your functor is wrong. You have:

                Stuart Dootson wrote:

                struct Finder : std::unary_function<bool, int>

                It should read:

                struct Finder : std::unary_function<int, bool>

                Here's the definition of std::unary_function from <functional>:

                // TEMPLATE STRUCT unary_function
                template<class _A, class _R>
                struct unary_function {
                typedef _A argument_type;
                typedef _R result_type;
                };

                The result type comes second, not first (which I've always thought was strange). Also, you should be #includeing <functional> for std::unary_function, as things stand you seem to be relying on some other include file including it indirectly. And finally, this technique is not very efficient. Try something like this:

                // VanillaConsole.cpp : Defines the entry point for the console application.
                //
                 
                #include "stdafx.h"
                #include <iostream>
                #include <vector>
                #include <algorithm>
                #include <iterator>
                 
                void main()
                {
                using namespace std;
                 
                // Create a vector and fill it with data.
                typedef vector<int> data_t;
                data_t data;
                data.push_back(1);
                data.push_back(3);
                data.push_back(2);
                data.push_back(1);
                data.push_back(5);
                data.push_back(1);
                 
                // Show the user the contents before messing with it.
                cout << "Contents before:" << endl;
                copy(data.begin(), data.end(), ostream_iterator<int>(cout, " "));
                cout << endl << endl;
                 
                // Remove the duplicates.
                sort(data.begin(), data.end());
                data_t::iterator new_end = unique(data.begin(), data.end());
                 
                // Show the user the contents with duplicates removed (and sorted).
                cout < "Contents after:" < endl;
                copy(data.begin(), new_end, ostream_iterator<int>(cout, " "));
                cout << endl << endl;
                }

                Steve

                S 1 Reply Last reply
                0
                • S s196675m

                  HI I am new to this STL form. I have a simple question, unique does not work as expected. Here is my test code

                  			int iList\[4\] = {0};
                  			iList\[0\] = -131;
                  			iList\[1\] = -131;
                  			iList\[2\] = -343455555;
                  			iList\[3\] = -131;
                  
                  			vector<int> iNeighborList(iList, iList + 4);
                  			vector<int>::iterator it;
                  			
                  			it = unique(iNeighborList.begin(), iNeighborList.end());
                  
                  			iNeighborList.resize(it - iNeighborList.begin());
                  

                  // At this point
                  //expected elements of iNeighborList are -131, -343455555
                  // but actual element I got are -131,-343455555, -131
                  // Why third element apprear?

                  			it = remove(iNeighborList.begin(),iNeighborList.end(),-343455555); 
                  			iNeighborList.resize(it - iNeighborList.begin());
                  
                  			int isiz = iNeighborList.size();
                  

                  I am using VS2005 to compile it using Pure MSIL (/clr:pure) switch. Can anybody help me why I am getting uncexppected result. Thank you

                  S Offline
                  S Offline
                  Stephen Hewitt
                  wrote on last edited by
                  #8

                  Here's[^] how I'd do it.

                  Steve

                  1 Reply Last reply
                  0
                  • S Stephen Hewitt

                    The definition of your functor is wrong. You have:

                    Stuart Dootson wrote:

                    struct Finder : std::unary_function<bool, int>

                    It should read:

                    struct Finder : std::unary_function<int, bool>

                    Here's the definition of std::unary_function from <functional>:

                    // TEMPLATE STRUCT unary_function
                    template<class _A, class _R>
                    struct unary_function {
                    typedef _A argument_type;
                    typedef _R result_type;
                    };

                    The result type comes second, not first (which I've always thought was strange). Also, you should be #includeing <functional> for std::unary_function, as things stand you seem to be relying on some other include file including it indirectly. And finally, this technique is not very efficient. Try something like this:

                    // VanillaConsole.cpp : Defines the entry point for the console application.
                    //
                     
                    #include "stdafx.h"
                    #include <iostream>
                    #include <vector>
                    #include <algorithm>
                    #include <iterator>
                     
                    void main()
                    {
                    using namespace std;
                     
                    // Create a vector and fill it with data.
                    typedef vector<int> data_t;
                    data_t data;
                    data.push_back(1);
                    data.push_back(3);
                    data.push_back(2);
                    data.push_back(1);
                    data.push_back(5);
                    data.push_back(1);
                     
                    // Show the user the contents before messing with it.
                    cout << "Contents before:" << endl;
                    copy(data.begin(), data.end(), ostream_iterator<int>(cout, " "));
                    cout << endl << endl;
                     
                    // Remove the duplicates.
                    sort(data.begin(), data.end());
                    data_t::iterator new_end = unique(data.begin(), data.end());
                     
                    // Show the user the contents with duplicates removed (and sorted).
                    cout < "Contents after:" < endl;
                    copy(data.begin(), new_end, ostream_iterator<int>(cout, " "));
                    cout << endl << endl;
                    }

                    Steve

                    S Offline
                    S Offline
                    Stuart Dootson
                    wrote on last edited by
                    #9

                    You might note the first sentence of the post you're replying to:

                    If the order of elements is unimportant, sort the vector (with std::sort) before using unique.

                    The whole reason for using the set and stuff is to preserve the order of the elements.

                    S 1 Reply Last reply
                    0
                    • S Stuart Dootson

                      You might note the first sentence of the post you're replying to:

                      If the order of elements is unimportant, sort the vector (with std::sort) before using unique.

                      The whole reason for using the set and stuff is to preserve the order of the elements.

                      S Offline
                      S Offline
                      Stephen Hewitt
                      wrote on last edited by
                      #10

                      I missed that.

                      Steve

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups