What is the best way to sort a vector leaving the original one unaltered?

Related searches

As the title says, I'm looking for a way to sort a vector without modifying the original one. My first idea is of course to create a copy of the vector before the sort, e.g.:

std::vector<int> not_in_place_sort(const std::vector<int>& original)
{
   auto copy = original;
   std::sort(copy.begin(), copy.end());
   return copy;
}

However, maybe there is a more efficient way to perform the sort using C++ standard algorithm (maybe a combination of sort and transform?)

Use partial_sort_copy. Here is an example:

vector<int> v{9,8,6,7,4,5,2,0,3,1};
vector<int> v_sorted(v.size());
partial_sort_copy(begin(v), end(v), begin(v_sorted), end(v_sorted));

Now, v remains untouched but v_sorted contains {0,1,2,3,4,5,6,7,8,9}.

Sorting a vector in C++, ISO CS Solved Papers � IRSO CS Original Papers and Official Keys C++ program to sort a vector in non-decreasing vector< int > v{ 1, 5, 8, 9, 6, 7, 3, 4, 2 , 0 }; This function does comparison in a way that puts greater element We use cookies to ensure you have the best browsing experience on our� Sort elements in range. Sorts the elements in the range [first,last) into ascending order. The elements are compared using operator< for the first version, and comp for the second. Equivalent elements are not guaranteed to keep their original relative order (see stable_sort ).

Here is my favorite. Sort an index and not the original array/vector itself.

#include <algorithm>

int main() {

    int intarray[4] = { 2, 7, 3, 4 };//Array of values
    //or you can have vector of values as below
    //std::vector<int> intvec = { 2, 7, 3, 4 };//Vector of values
    int indexofarray[4] = { 0, 1, 2, 3 };//Array indices

    std::sort(indexofarray, indexofarray + 4, [intarray](int index_left, int index_right) { return intarray[index_left] < intarray[index_right]; });//Ascending order.
    //have intvec in place of intarray for vector.


}

After this, indexofarray[] elements would be 0, 2, 3, 1, while intarray[] is unchanged.

Sorting A Vector In C++, Here we'll look at one of the most common data manipulation tasks - sorting. To get the ball rolling, let's see how to sort a vector of integers. In our simple example above, we left out the third parameter, comp, so the Sometimes this behavior is undesireable; we want to retain the original order of� We can sort such arrays more efficiently with the help of Heap data structure. Following is the detailed process that uses Heap. 1) Create a Min Heap of size k+1 with first k+1 elements. This will take O(k) time (See this GFact) 2) One by one remove min element from heap, put it in result array, and add a new element to heap from remaining elements.

As suggested in the comments pass the function argument by value std::vector<int> original:

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

std::vector<int> not_in_place_sort(std::vector<int> original) {
    std::sort(original.begin(), original.end());
    return original;
}

int main() {
    std::vector<int> v = { 8, 6, 7, 2, 3, 4, 1, 5, 9 };
    std::vector<int> v2 = not_in_place_sort(v); // pass the vector by value
    std::cout << "v1: " << '\n';
    for (auto el : v) {
        std::cout << el << ' ';
    }
    std::cout << "\nv2: " << '\n';
    for (auto el : v2) {
        std::cout << el << ' ';
    }
}

That will sort a copy of your original vector leaving the original intact. As pointed out below this might restrict some optimizations such as RVO but will call vector's move constructor in the return statement instead.

5. Data Structures — Python v3.1.5 documentation, The list methods make it very easy to use a list as a stack, where the last second to arrive now leaves 'John' >>> queue # Remaining queue in order of arrival It is best to think of a dictionary as an unordered set of key: value pairs, with If one sequence is an initial sub-sequence of the other, the shorter� The values_to_sort list has been changed in place, and the original order is not maintained in any way. These differences in behavior make .sort() and sorted() absolutely not interchangeable in code, and they can produce wildly unexpected outcomes if one is used in the wrong way.

For the case where you are interested in proxy sorting (sorting an index list), you may want to implement a more flexible algorithm that allows you to deal with containers which do not support random access (such as std::list). For example:

#include <algorithm>
#include <iostream>
#include <list>
#include <numeric>
#include <vector>

template <typename Container>
auto sorted_indices(const Container& c) {
  std::vector<typename Container::size_type> indices(c.size());
  std::iota(indices.begin(), indices.end(), 0);
  std::sort(indices.begin(), indices.end(), [&c](auto lhs, auto rhs) {
    return (*(std::next(c.begin(), lhs)) < *(std::next(c.begin(), rhs)));
  });
  return indices;
}

template <typename Container, typename Indices>
auto display_sorted(const Container& c, const Indices& indices) {
  std::cout << "sorted: ";
  for (auto&& index : indices) {
    std::cout << *(std::next(c.begin(), index)) << " ";
  }
  std::cout << std::endl;
}

template <typename Container>
auto display_sorted(const Container& c) {
  return display_sorted(c, sorted_indices(c));
}

template <typename Container>
auto display(const Container& c) {
  std::cout << "as provided: ";
  for (auto&& ci : c) std::cout << ci << " ";
  std::cout << std::endl;
}

int main() {
  // random access
  const std::vector<int> a{9, 5, 2, 3, 1, 6, 4};
  display(a);
  display_sorted(a);
  display(a);

  std::cout << "---\n";

  // no random access
  const std::list<int> b{9, 5, 2, 3, 1, 6, 4};
  display(b);
  display_sorted(b);
  display(b);
}

Sample run:

$ clang++ example.cpp -std=c++17 -Wall -Wextra
$ ./a.out
as provided: 9 5 2 3 1 6 4 
sorted: 1 2 3 4 5 6 9 
as provided: 9 5 2 3 1 6 4 
---
as provided: 9 5 2 3 1 6 4 
sorted: 1 2 3 4 5 6 9 
as provided: 9 5 2 3 1 6 4 

As you would expect, relying on proxy sorting could have important performance implications. For example: every time you want to traverse in order, you will possibly incur cache misses. In addition, the traversal will have the same complexity as the underlying container for random access: In the case of std::vector, std::next(v.begin(), n) is O(1), but in the case of std::list, std::next(l.begin(), n) is O(n).

5. Data Structures — Python 3.3.7 documentation, You might have noticed that methods like insert, remove or sort that modify the list have [1] This is a design principle for all mutable data structures in Python. The initial expression in a list comprehension can be any arbitrary function which returns a new sorted list while leaving the source unaltered. Teams. Q&A for Work. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.

For int's it doesn't make much difference if you're sorting an index or making a copy & sorting the copy; the data still needs to be initialized, and in the case of the indexes, this will involve a loop assigning values rather than faster memcpy routines; so may end up slower; in addition you're going to be jumping around memory lots more; so now the cache can't do its job nicely.

For larger objects I'd not sort the index, but use a vector of pointers. The copy of the pointers is cheap compared to copying the objects themselves; the containers are still obvious because they're containing pointers of your object; and the sort isn't attempting to reference another vector.

[PDF] An introduction to R, 2.2.1 Vectors . important differences, but much code written for S runs unaltered under R. R provides a wide Use the function ordered and specify the order with the levels argument. The easiest way is to use the column operator (:). By default the merge function leaves out rows that where not matched, consider the. Tips for Social Distancing. When going out in public, it is important to stay at least 6 feet away from other people and wear a mask to slow the spread of COVID-19. Consider the following tips for practicing social distancing when you decide to go out.

A Survivor's Guide to R: An Introduction for the Uninitiated and , Sorting and conditionally selecting parts of a data set is central to most R it has the advantage of allowing you to leave the original data unaltered. We'll learn how to set up selection vectors to automate the process of filtering USING INDEX VALUES TO SELECT DATA I hope you recall the discussion in Chapters 1� The idea is to traverse from rightmost side and find the first out of order element (element which is smaller than previous element). Once first element is found, find the other our of order element by traversing the array toward left side. Below is implementation of above idea.

Consider you have instances of this type: [code]struct person { string last_name; string first_name; int id; }; [/code]If you want to sort an array of such instances by lastname, firstname and id, you can do something like this: [code]void sor

If a and b are two elements being compared, then: If compareFunction (a, b) returns less than 0, sort a to an index lower than b (i.e. a comes first). If compareFunction (a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements.

Comments
  • Pass the vector by value, so it's local to the function, sort and return. That's the best you can get.
  • @JakeFreeman no it's not, it's a fast 'on average' sort, but I think you should revisit sorting algorithms before making such blanket statements
  • Explain what you mean by "sort". If you want a sorted vector, you can't possibly get away without a copy and sort.
  • I'm just wondering if there is an algorithm f(v) whose time cost is less than create_copy + std::sort. If I need to copy the vector, I can do it, just wondering if I'm missing something
  • @Emiliano -- One option -- don't sort the vector itself -- you can sort an index array and use that to index into the vector.
  • This solution is underrated.
  • This solution is overrated: it provides no explanation as to why partial_sort_copy is better than initially copying the vector and calling std::sort on the result. It's not a "partial" whenever two range lengths are the same. Is it faster? Is it more readable? I would argue the answer is "no" for both.
  • That inhibits RVO. It isn't a big deal because the return will be moved, but depending on the application, it could matter.
  • How does this prohibit RVO? I think it should work as described. Better yet, v = not_in_place_sort(std::move(v)) should be very nearly as cheap as std::sort(v.begin(), v.end()).
  • OK interesting, it does prevent RVO. Still, as long as the containers have move constructors, passing by value and returning by value give the most flexibility and improve the clarity of the calling code: sorted(std::move(v)) means assuming v will no longer be valid after the funciton, sorted(v) means it will still be valid.