0

In the code below, I get segmentation fault. I think the problem is with indexing but I don't understand why. Is it possible to use std::sort and lambda function to sort a vector based on another vector?

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

int main()
{
    std::vector<std::string> A = {"b", "a", "c"};
    std::vector<int> B = {2, 1, 3};

    std::sort(std::begin(A), std::end(A),
            [&](const std::string& t1, const std::string& t2)
            {
            return B[&t1-A.data()] > B[&t2-A.data()]; // problem could be here!
            });

    std::cout << A[0] << std::endl;
    std::cout << A[1] << std::endl;
    std::cout << A[2] << std::endl;

    return 0;
}
Shibli
  • 5,879
  • 13
  • 62
  • 126
  • 3
    `&t1-A.data()` that does not look like it should be used to index into a vector – 463035818_is_not_an_ai Dec 06 '17 at 15:00
  • you know that `&t1` is a memory address? – 463035818_is_not_an_ai Dec 06 '17 at 15:03
  • @tobi303 it makes sense to find what element t1 is. – Jake Freeman Dec 06 '17 at 15:04
  • @tobi303 `std::vector::data` returns a pointer to a `std::vector` s internal buffer. – George Dec 06 '17 at 15:04
  • @JakeFreeman I dont understand what you mean – 463035818_is_not_an_ai Dec 06 '17 at 15:05
  • @George that doesnt make this way of indexing less wrong, does it? – 463035818_is_not_an_ai Dec 06 '17 at 15:05
  • 5
    You're not taking into account that elements can move around during the sort. – chris Dec 06 '17 at 15:06
  • @tobi303 It doesn't, I just didn't understand why/how "you know that &t1 is a memory address?" is relevant? :) – George Dec 06 '17 at 15:07
  • 3
    What is the real goal? Is it to sort a vector of indices into the `A` vector without having to actually sort the `A` vector? If so, the approach is incorrect. – PaulMcKenzie Dec 06 '17 at 15:08
  • @George yes, actually it took me a minute to realize that `&t1 - A.data()` can result in a valid index, but still it is as obfuscated as it can get imho – 463035818_is_not_an_ai Dec 06 '17 at 15:09
  • @PaulMcKenzie I want to sort `B` and then order the elements of `A` accordingly. But mainly I would like to know why I get segmentation fault. – Shibli Dec 06 '17 at 15:20
  • @Shibli -- *I would like to know why I get segmentation fault.* -- What if you printed out the value of `&t1 - A.data()`? Does that value equate to a valid index into the `B` array? [Look at this example](http://coliru.stacked-crooked.com/a/462ee4b63ffd58da). Basically all it took was a simple `cout` to see right away this would not have worked. Again, if your goal is to have `B` to act as an index array into `A`, then the links provided in the comments shows how to do this. – PaulMcKenzie Dec 06 '17 at 19:08
  • @Shibli -- [Here is proof of the crash, using `at()`](http://coliru.stacked-crooked.com/a/8516060e6cdd115a). So that answers your question -- the array index is out of bounds, way, way, out of bounds,. – PaulMcKenzie Dec 06 '17 at 19:14
  • @Shibli -- [Is this what you're really trying to accomplish](http://coliru.stacked-crooked.com/a/dbc26f8125074e11)? – PaulMcKenzie Dec 06 '17 at 19:22

1 Answers1

0

Rather than doing your way to get the index a simple way to do it.

std::sort(std::begin(A), std::end(A),
        [&](const std::string& t1, const std::string& t2)
        {
          int index1, index2;
          for(int i = 0; i<A.size(); i++) {
            if(&A[i] == &t1) index1 = i;
            if(&A[i] == &t2) index2 = i;
          }
        return B[index1] > B[index2];
        });

This way is safe and ensures that it gets the right index. After testing it the output is C \n B \n A which is what I think you want.

Hope this helps.

Jake Freeman
  • 1,700
  • 1
  • 8
  • 15