STL.h
Go to the documentation of this file.
00001 /*      
00002  * File: STL.h
00003  * Project: DUtils library
00004  * Author: Dorian Galvez-Lopez
00005  * Date: November 2010
00006  * Description: STL-related functions
00007  *
00008  * 
00009  * This program is free software: you can redistribute it and/or modify
00010  * it under the terms of the GNU Lesser General Public License as published by
00011  * the Free Software Foundation, either version 3 of the License, or
00012  * any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public License
00020  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00021  *
00022  */
00023 
00024 #pragma once
00025 #ifndef __D_STL__
00026 #define __D_STL__
00027 
00028 #include <vector>
00029 #include <algorithm>
00030 
00031 namespace DUtils {
00032 
00033 class STL {
00034 public:
00035 
00044   template<class T>
00045   static void removeIndices(std::vector<T> &data, 
00046     const std::vector<unsigned int> &indices, bool preserve_order = true);
00047   
00056   template<class T>
00057   static void removeIndices(std::vector<T> &data, 
00058     std::vector<unsigned int> &indices, bool preserve_order = true);
00059 
00060 };
00061 
00062 // ---------------------------------------------------------------------------
00063 
00064 template<class T>
00065 void STL::removeIndices(std::vector<T> &data, 
00066   const std::vector<unsigned int> &indices, bool preserve_order)
00067 {
00068   if(indices.empty()) return;
00069   
00070   std::vector<unsigned int> copied_indices = indices;
00071   STL::removeIndices(data, copied_indices, preserve_order);
00072 }
00073 
00074 // ---------------------------------------------------------------------------
00075 
00076 template<class T>
00077 void STL::removeIndices(std::vector<T> &data, 
00078   std::vector<unsigned int> &indices, bool preserve_order)
00079 {
00080   if(indices.empty()) return;
00081   
00082   // sort the index entries    
00083   std::sort(indices.begin(), indices.end()); // ascending order
00084   
00085   // remove those indices that exceed the data vector length
00086   {
00087     int i_idx = (int)indices.size() - 1;
00088     while( indices[i_idx] >= data.size() ) i_idx--;
00089     indices.resize(i_idx+1);
00090   }
00091     
00092   // make sure there are no repeated indices
00093   {
00094     const std::vector<unsigned int>::iterator last =
00095       std::unique(indices.begin(), indices.end());
00096     indices.erase(last, indices.end());
00097   }
00098     
00099   // go
00100   if(preserve_order)
00101   {
00102     // remove indices in descending order, grouping when possible
00103     int i_idx = (int)indices.size() - 1;
00104     while(i_idx >= 0)
00105     {
00106       int j_idx = i_idx - 1;
00107       while(j_idx >= 0 && ((int)(indices[i_idx] - indices[j_idx]) == i_idx - j_idx))
00108       {
00109         j_idx--;
00110       }
00111       data.erase(data.begin() + indices[j_idx + 1], 
00112         data.begin() + indices[i_idx] + 1);
00113       i_idx = j_idx;
00114     }
00115     
00116   }
00117   else
00118   { 
00119     // swap with the last items
00120     int nremoved = 0;
00121     
00122     const typename std::vector<T>::iterator first = data.begin();
00123     const typename std::vector<T>::iterator last = data.end()-1;
00124   
00125     int i_idx = (int)indices.size() - 1;
00126     
00127     // exception case: removing items are at the end of the vector
00128     while(i_idx >= 0 && 
00129       (indices.size() - i_idx == data.size() - indices[i_idx]))
00130     {
00131       i_idx--;
00132       nremoved++;
00133     }
00134         
00135     while(i_idx >= 0)
00136     {
00137       int j_idx = i_idx - 1;
00138       while(j_idx >= 0 && ((int)(indices[i_idx] - indices[j_idx]) == i_idx - j_idx))
00139       {
00140         j_idx--;
00141       }
00142       
00143       int nremoving = i_idx - j_idx;
00144       
00145       const typename std::vector<T>::iterator cpy_end = last - nremoved + 1;
00146       const typename std::vector<T>::iterator cpy_src = cpy_end - 
00147         MIN( nremoving, (int)data.size()-1 - nremoved - (int)indices[i_idx] );
00148       const typename std::vector<T>::iterator trg = first + indices[j_idx + 1];
00149             
00150       std::copy( cpy_src, cpy_end, trg );
00151       
00152       nremoved += nremoving;
00153       i_idx = j_idx;
00154     }
00155     
00156     data.resize(data.size() - nremoved);
00157 
00158     // v2, presumedly slower
00159 #if 0
00160     std::vector<unsigned int>::reverse_iterator rit;
00161     for(rit = indices.rbegin(); rit != indices.rend(); ++rit)
00162     {
00163       if(*rit < data.size())
00164       {
00165         *(first + *rit) = *(last - nremoved);
00166         nremoved++;
00167       }
00168     }
00169     data.resize(data.size() - nremoved);
00170 #endif
00171   }
00172   
00173 }
00174 
00175 // ---------------------------------------------------------------------------
00176 
00177 }
00178 
00179 #endif
00180 


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:33:00