C++ sorting and keeping track of indexes

后端 未结 15 2011
甜味超标
甜味超标 2020-11-22 10:01

Using C++, and hopefully the standard library, I want to sort a sequence of samples in ascending order, but I also want to remember the original indexes of the new samples.<

相关标签:
15条回答
  • 2020-11-22 10:16

    If it's possible, you can build the position array using find function, and then sort the array.

    Or maybe you can use a map where the key would be the element, and the values a list of its position in the upcoming arrays (A, B and C)

    It depends on later uses of those arrays.

    0 讨论(0)
  • 2020-11-22 10:21

    There is another way to solve this, using a map:

    vector<double> v = {...}; // input data
    map<double, unsigned> m; // mapping from value to its index
    for (auto it = v.begin(); it != v.end(); ++it)
        m[*it] = it - v.begin();
    

    This will eradicate non-unique elements though. If that's not acceptable, use a multimap:

    vector<double> v = {...}; // input data
    multimap<double, unsigned> m; // mapping from value to its index
    for (auto it = v.begin(); it != v.end(); ++it)
        m.insert(make_pair(*it, it - v.begin()));
    

    In order to output the indices, iterate over the map or multimap:

    for (auto it = m.begin(); it != m.end(); ++it)
        cout << it->second << endl;
    
    0 讨论(0)
  • 2020-11-22 10:22

    Consider using std::multimap as suggested by @Ulrich Eckhardt. Just that the code could be made even simpler.

    Given

    std::vector<int> a = {5, 2, 1, 4, 3};  // a: 5 2 1 4 3
    

    To sort in the mean time of insertion

    std::multimap<int, std::size_t> mm;
    for (std::size_t i = 0; i != a.size(); ++i)
        mm.insert({a[i], i});
    

    To retrieve values and original indices

    std::vector<int> b;
    std::vector<std::size_t> c;
    for (const auto & kv : mm) {
        b.push_back(kv.first);             // b: 1 2 3 4 5
        c.push_back(kv.second);            // c: 2 1 4 3 0
    }
    

    The reason to prefer a std::multimap to a std::map is to allow equal values in original vectors. Also please note that, unlike for std::map, operator[] is not defined for std::multimap.

    0 讨论(0)
  • 2020-11-22 10:23

    Beautiful solution by @Lukasz Wiklendt! Although in my case I needed something more generic so I modified it a bit:

    template <class RAIter, class Compare>
    vector<size_t> argSort(RAIter first, RAIter last, Compare comp) {
    
      vector<size_t> idx(last-first);
      iota(idx.begin(), idx.end(), 0);
    
      auto idxComp = [&first,comp](size_t i1, size_t i2) {
          return comp(first[i1], first[i2]);
      };
    
      sort(idx.begin(), idx.end(), idxComp);
    
      return idx;
    }
    

    Example: Find indices sorting a vector of strings by length, except for the first element which is a dummy.

    vector<string> test = {"dummy", "a", "abc", "ab"};
    
    auto comp = [](const string &a, const string& b) {
        return a.length() > b.length();
    };
    
    const auto& beginIt = test.begin() + 1;
    vector<size_t> ind = argSort(beginIt, test.end(), comp);
    
    for(auto i : ind)
        cout << beginIt[i] << endl;
    

    prints:

    abc
    ab
    a
    
    0 讨论(0)
  • 2020-11-22 10:23

    Make a std::pair in function then sort pair :

    generic version :

    template< class RandomAccessIterator,class Compare >
    auto sort2(RandomAccessIterator begin,RandomAccessIterator end,Compare cmp) ->
       std::vector<std::pair<std::uint32_t,RandomAccessIterator>>
    {
        using valueType=typename std::iterator_traits<RandomAccessIterator>::value_type;
        using Pair=std::pair<std::uint32_t,RandomAccessIterator>;
    
        std::vector<Pair> index_pair;
        index_pair.reserve(std::distance(begin,end));
    
        for(uint32_t idx=0;begin!=end;++begin,++idx){
            index_pair.push_back(Pair(idx,begin));
        }
    
        std::sort( index_pair.begin(),index_pair.end(),[&](const Pair& lhs,const Pair& rhs){
              return cmp(*lhs.second,*rhs.second);
        });
    
        return index_pair;
    }
    

    ideone

    0 讨论(0)
  • 2020-11-22 10:23

    Are the items in the vector unique? If so, copy the vector, sort one of the copies with STL Sort then you can find which index each item had in the original vector.

    If the vector is supposed to handle duplicate items, I think youre better of implementing your own sort routine.

    0 讨论(0)
提交回复
热议问题