2

I have some vectors like this:

vector<int> vec {3;0;1;0;5}; 
vector<int> vec1{3;2;1;7;5};

I want to sort them in ascending order but, if they contain any elements that are zero, the must be moved to the end of the vector.

My desired result is:

 vector<int> vec {1;3;5;0;0};
 vector<int> vec1 {1;2;3;5;7}; 

I used the following code; however, the order of elements is unchanged:

std::sort(vec.begin(), vec.end(), [](int a, int b)
            {
              return a < b && a>0;;  
            });

How can I fix this?

4
  • 5
    That is not the proper way to initialize an std::vector. Did you perhaps want: vector<int> vec {3, 0, 1, 0, 5};? Commented Aug 29, 2021 at 17:08
  • 3
    I'd suggest just sorting first, and then in a second step moving all the 0s to the end. For the latter you might want stable_partition. Commented Aug 29, 2021 at 17:08
  • 1
    If you were to explain what your comparison function's logic should be, in plain English, how would you do it? Would you say "zero is greater than all other values, otherwise it's normal comparison order". Would that be an accurate description of what you're trying to do? Do you think the shown code's logic matches this description? How would you change it, so that it does? Commented Aug 29, 2021 at 17:10
  • 3
    I really don't see what "detail or clarity" is required here. I have voted to reopen. Commented Aug 29, 2021 at 17:42

3 Answers 3

2

Your sort algorithm should take into account a zero in either position. So, if b is zero, then return true if a is not zero, or false if a is also zero; otherwise, if a is zero, return false; otherwise (neither is zero), return the result of the normal comparison.

Here's a working example, using your data (note also the correction to the way the vectors are initialized – using a comma separator, rather than a semicolon):

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

int main()
{
    std::vector<int> vec1{ 3, 0, 1, 0, 5 };
    std::vector<int> vec2{ 3, 2, 1, 7, 5 };

    auto mySort = [](const int& a, const int& b)
    {
        // For "short-circuiting" to work, the ORDER of the comparisons is critical!
        return (b == 0 && a != 0) || (a != 0 && a < b);
    };

    std::sort(vec1.begin(), vec1.end(), mySort);
    for (auto i : vec1) std::cout << i << " "; // 1 3 5 0 0
    std::cout << std::endl;

    std::sort(vec2.begin(), vec2.end(), mySort);
    for (auto i : vec2) std::cout << i << " "; // 1 2 3 5 7
    std::cout << std::endl;

    return 0;
}

As pointed out in the comment by Nathan Pierson, the comparator function should return false for two equal values, even if those are both zero.

Sign up to request clarification or add additional context in comments.

2 Comments

mySort(0, 0) should be false, shouldn't it? The comparator models < not <=.
@NathanPierson Yes - excellent point. I have edited accordingly. The 'original' risked possible infinite run-time. Thanks.
2

Since you want the zeros to appear at the end of the sorted sequence, you could take in consideration this special value in any case.

I suggest the following closure

[](int a, int b)
{
  return a==0 ? false       // a after b in any case
              : b==0 ? true // b after a in any case
                     : a<b; // usual comparison
}

Comments

2

There are answers showing how to write the comparator for std::sort correctly, but another option is to first partition the vector into non-zero and zero elements, and then sort the non-zero elements. This way is less error prone (since you can use the default comparator, instead of writing one), and is more efficient, since you have to sort fewer elements.

auto p = std::partition(std::begin(vec), std::end(vec), 
                        [](int n) { return n; });  

std::sort(std::begin(vec), p);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.