Raph Schim
Raph Schim

Reputation: 538

Way to replace one vector with another

I'm sorting 2 vectors using a vector of index.

the 2 vectors have not the same size. One vector (keys) is size X and the other (descriptors) is size X*128 (one key is parametrized by 128 values).

In order to create the vector of index, I generated a vector of unsigned, and used the iota function to put in this vector [0,1,2,...,X] then I use the sort function to sort these index depending scale of a key (keys[i].s).

After that, I generate another vector in which I copy the values using the vector of index for both descriptors and keys (calling them descriptors_tmp, and keys_tmp), and then I want to make the first keys vector equal to the keys_tmp, and the same for descriptors equals to descriptors_tmp. My question are :

-Is there a way to make that without making any copy. Since I don't need the previous version of keys and descriptors, I could just make the vector point on the other vector (something like *keys = *keys_tmp) ?

-Is there an easier way to achieve what I'm trying to achieve?

My code :

void _siftMatch::getIdxOfSorting(std::vector<unsigned>& idx_scale_order)
{
    //keys[i].s is the scale and I sort depending decreasing scale
    auto cmp_scale = [this](int i, int j) {
        return keys[i].s > keys[j].s;
    };

    std::sort(idx_scale_order.begin(), idx_scale_order.end(), cmp_scale);
}   

void _siftMatch::sort() {
    //vector containing the index of sorted
    std::vector<unsigned>idx_scale_order;
    idx_scale_order.resize(keys.size());
    //Generate [0,1,...,X]
    std::iota(idx_scale_order.begin(), idx_scale_order.end(), 0); 

    //Sort the vector
    getIdxOfSorting(idx_scale_order); 

    std::vector<float> descriptors_tmp;
    std::vector<SiftGPU::SiftKeypoint> keys_tmp;

    for (int i = 0; i < idx_scale_order.size(); ++i) {
        keys_tmp.push_back(keys[idx_scale_order[i]]);
        for (int j = 0; j < 128; ++j)
            descriptors_tmp.push_back(descriptors[idx_scale_order[i] * 128 + j]);
     }
    //This is here that I want to put descriptors_tmp and keys_tmp in descriptors and keys
    //descriptors.swap(descriptors_tmp.data);
}

Upvotes: 0

Views: 1431

Answers (1)

rcgldr
rcgldr

Reputation: 28921

Is there a way to make that without making any copy

This example of sorting 3 arrays according to one of the arrays, using a 4th generated array of indices that are sorted according to one of the 3 arrays may help. The key part of this is the in place reordering of all 4 arrays according to the array of indices. You'll need to modify this for your situation. I'm not sure why you are converting the array of indices to an array of numeric strings (via the itoa calls), using the indices directly works better for the example in this answer.

// sort 3 vectors according to one of them

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

int main()
{
    std::vector <int> A;                // ages
    std::vector <std::string> N;        // names
    std::vector <int> Z;                // zip codes
    std::vector <size_t> I;             // indices
    int tA;
    std::string tN;
    int tZ;

    A.push_back(37);
    N.push_back("Ted");
    Z.push_back(54211);
    A.push_back(21);
    N.push_back("John");
    Z.push_back(53421);
    A.push_back(31);
    N.push_back("Fred");
    Z.push_back(52422);
    A.push_back(21);
    N.push_back("Sam");
    Z.push_back(51422);
    // display the vectors
    for(size_t i = 0; i < A.size(); i++)
        std::cout << std::setw(6) << N[i]
            << std::setw(8) << Z[i]
            << std::setw(4) << A[i] << std::endl;
    std::cout << std::endl;
    // initialize the vector of indices
    for(size_t i = 0; i < A.size(); i++)
        I.push_back(i);
    // sort I according to A
    std::stable_sort(I.begin(), I.end(),
        [&A](size_t i, size_t j) {return 
        A[i] < A[j];});
    // reorder A, N, Z in place also restore I
    // time complexity is O(n)
    for(size_t i = 0; i < A.size(); i++){
        size_t j, k;
        if(i != I[i]){
            tA = A[i];
            tN = N[i];
            tZ = Z[i];
            k = i;
            while(i != (j = I[k])){
                A[k] = A[j];
                N[k] = N[j];
                Z[k] = Z[j];
                I[k] = k;
                k = j;
            }
            A[k] = tA;
            N[k] = tN;
            Z[k] = tZ;
            I[k] = k;
        }
    }
    // display the sorted vectors
    for(size_t i = 0; i < A.size(); i++)
        std::cout << std::setw(6) << N[i]
            << std::setw(8) << Z[i]
            << std::setw(4) << A[i] << std::endl;
    return 0;
}

Upvotes: 1

Related Questions