STL: Keeping Only Unique String Characters AND Preserving Order

49 Views Asked by At

std::set and std::unordered_set on a string both pull out the unique characters only, but neither leaves the characters in the original order as they appeared in the string.

There's so much of the STL I am ignorant of, but I wondered if there was an STL way of getting just the unique characters from the string WITHOUT losing the original order and WITHOUT resorting to loops. I can do it with iterators, loops and, for example, std::remove , but I wondered if there was a more elegant way. This thought train was triggered by today's GeeksforGeeks problem, so the test string was "geEksforGEeks" which should end up as "geEksforG" (case sensitive, 'g' != 'G').

Thoughts?

1

There are 1 best solutions below

2
Pepijn Kramer On

There will be many options, like using std::remove_if, or in this example std::copy_if

#include <string>
#include <array>
#include <algorithm>
#include <iostream>

std::string without_duplicates(const std::string& input)
{
    std::array<bool,256ul> seen{}; // initialize all "seen" characters to false
    std::string output;

    // std::back_inserter allows you to copy to an "empty" collection by adding elements at the end
    // copy_if takes a lambda expression which will be called for each character in the input string.
    std::copy_if(input.begin(),input.end(),std::back_inserter<std::string>(output),[&](const char c)
    {
        bool copy_to_output_string = !seen[c];
        seen[c] = true;
        return copy_to_output_string;
    });

    return output;
}

std::string without_duplicates2(const std::string& input)
{
    std::string output;
    std::set<char> set;
    for(const auto c : input)
    {
        if (!set.contains(c)) { output += c; set.insert(c); }
    }
    return output;
}

int main()
{
    auto result = without_duplicates("geEksforGEeks");
    std::cout << result;
}