LCOV - code coverage report
Current view: top level - snapdev - remove_duplicates.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 21 21 100.0 %
Date: 2023-05-29 16:11:08 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2023  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/snapdev
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software: you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation, either version 3 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License
      17             : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18             : //
      19             : // Based on: http://stackoverflow.com/questions/236129/split-a-string-in-c#1493195
      20             : //
      21             : #pragma once
      22             : 
      23             : /** \file
      24             :  * \brief Template used to remove duplicates in a container.
      25             :  *
      26             :  * Some containers, such as a vector, allow for duplicates. This function
      27             :  * implements an algorithm to remove duplicates.
      28             :  *
      29             :  * We offer several solutions to the problem of removing duplicates:
      30             :  *
      31             :  * \li The default algorithm which sorts the values first; this is the
      32             :  * \em normal algorithm for such a feature.
      33             :  * \li Consider using a container that automatically sorts such as
      34             :  * `std::set<T>` and `std::map<T,bool>`.
      35             :  * \li There are unsorted versions of containers that you may be able
      36             :  * to use for the purpose.
      37             :  */
      38             : 
      39             : // C++
      40             : //
      41             : #include    <algorithm>
      42             : 
      43             : 
      44             : 
      45             : namespace snapdev
      46             : {
      47             : 
      48             : 
      49             : /** \brief Remove duplicates in the unsorted container.
      50             :  *
      51             :  * This function goes through the elements of your container and first
      52             :  * sorts and then eliminates duplicates.
      53             :  *
      54             :  * This function works well with vectors.
      55             :  *
      56             :  * \note
      57             :  * Maps and sets are already sorted and already do not include duplicates.
      58             :  * In other words, this function is useless for such containers.
      59             :  *
      60             :  * \warning
      61             :  * On return, the elements in the container are sorted.
      62             :  *
      63             :  * \tparam ContainerT  The type of container to de-dup.
      64             :  * \param[in,out] container  The container where duplicates get removed.
      65             :  *
      66             :  * \return The reference to the input container (NOT A COPY).
      67             :  *
      68             :  * \sa sorted_remove_duplicates()
      69             :  * \sa unsorted_remove_duplicates()
      70             :  */
      71             : template<typename ContainerT>
      72          21 : ContainerT & sort_and_remove_duplicates(ContainerT & container)
      73             : {
      74          21 :     std::sort(container.begin(), container.end());
      75             : 
      76          42 :     container.erase(std::unique(
      77             :                           container.begin()
      78             :                         , container.end())
      79          42 :                     , container.end());
      80             : 
      81          21 :     return container;
      82             : }
      83             : 
      84             : 
      85             : /** \brief Remove duplicates in the sorted container.
      86             :  *
      87             :  * This function goes through the elements of your container and eliminates
      88             :  * duplicates. The input must be sorted for the algorithm to work properly.
      89             :  *
      90             :  * \note
      91             :  * Maps and sets are already sorted and already do not include duplicates.
      92             :  * In other words, this function is useless for such containers.
      93             :  *
      94             :  * \tparam ContainerT  The type of container to de-dup.
      95             :  * \param[in,out] container  The container where duplicates get removed.
      96             :  *
      97             :  * \return The reference to the input container (NOT A COPY).
      98             :  *
      99             :  * \sa sort_and_remove_duplicates()
     100             :  */
     101             : template<typename ContainerT>
     102          41 : ContainerT & sorted_remove_duplicates(ContainerT & container)
     103             : {
     104          72 :     container.erase(std::unique(
     105             :                           container.begin()
     106             :                         , container.end())
     107          62 :                     , container.end());
     108             : 
     109          41 :     return container;
     110             : }
     111             : 
     112             : 
     113             : /** \brief Function to replace duplicate objects.
     114             :  *
     115             :  * This function goes through the items of a container and overwrite
     116             :  * entries as duplicates are found.
     117             :  *
     118             :  * \warning
     119             :  * Like std::unique(), this function does not itself remove anything.
     120             :  * You must make sure to use the std::erase() to remove the last few
     121             :  * items. This is done by the unsorted_remove_duplicates() function.
     122             :  *
     123             :  * \rparam ForwardIterator  The type of iterator from your container.
     124             :  * \param[in] first  Forward iterator to the container's first element.
     125             :  * \param[in] end  Forward iterator to the container's last element + 1.
     126             :  *
     127             :  * \return The new end of your container.
     128             :  *
     129             :  * \sa https://stackoverflow.com/questions/49863158/c-remove-duplicate-values-from-a-vector-without-sorting
     130             :  * \sa unsorted_remove_duplicates()
     131             :  */
     132             : template<typename ForwardIterator>
     133           4 : ForwardIterator remove_duplicates(ForwardIterator first, ForwardIterator end)
     134             : {
     135           4 :     auto new_end(first);
     136         326 :     for(auto current(first); current != end; ++current)
     137             :     {
     138         322 :         if(std::find(first, new_end, *current) == new_end)
     139             :         {
     140         240 :             if(new_end != current)
     141             :             {
     142         158 :                 *new_end = *current;
     143             :             }
     144         240 :             ++new_end;
     145             :         }
     146             :     }
     147             : 
     148           4 :     return new_end;
     149             : }
     150             : 
     151             : 
     152             : /** \brief Remove duplicates without sorting the container.
     153             :  *
     154             :  * This function goes through the elements of your container and eliminates
     155             :  * duplicates. The input does not have to be sorted and the returned function
     156             :  * does not change the order.
     157             :  *
     158             :  * The algorithm is O(n^2). If sorting is okay, then use the
     159             :  * sort_and_remove_duplicates() directly.
     160             :  *
     161             :  * \tparam ContainerT  The type of container to de-dup.
     162             :  * \param[in,out] container  The container where duplicates get removed.
     163             :  *
     164             :  * \return The reference to the input container (NOT A COPY).
     165             :  *
     166             :  * \sa remove_duplicates()
     167             :  */
     168             : template<typename ContainerT>
     169           4 : ContainerT & unsorted_remove_duplicates(ContainerT & container)
     170             : {
     171           8 :     container.erase(remove_duplicates(
     172             :                           container.begin()
     173             :                         , container.end())
     174           8 :                     , container.end());
     175             : 
     176           4 :     return container;
     177             : }
     178             : 
     179             : 
     180             : 
     181             : } // namespace snapdev
     182             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14