2

i meet a problem when i try to erase a duplicate struct item in std::vector. first I define a struct.

typedef unsigned int       uint32_t;

struct TokenTerm{
std::string     value;
std::string     type;
uint32_t        start_pos;
uint32_t        end_pos;
}

Then after several process I got a vector . and I define op :

struct equal4EntityTermSet
{
bool operator()(const TokenTerm&l_term, const TokenTerm&r_term)
{       
        if (l_term.type == r_term.type and l_term.norm_value == 
            r_term.norm_value and l_term.start_pos == r_term.start_pos
            and l_term.end_pos == r_term.end_pos )
        {
            return false;
        }
        return true;
    }
};

Next, I try to remove the duplicate TokenTerm by insert each item in set.

for(it = _query_term.m_entities.begin();it!= _query_term.m_entities.end(); it++)
{
    entSet.insert(*it);
}

_query_term.m_entities.clear();

for(itSet = entSet.begin(); itSet!=entSet.end(); itSet++)
{
    _query_term.m_entities.push_back(*itSet);
}

finally, it words partly. I erase same duplicate item .but it still exist duplicate. Then I print those items , they do exactly same with others( I compare it and print the bool value)

Hope help.

Liu
  • 21
  • 1
  • 1
    We don't see how you use `equal4EntityTermSet`, but should't its operator return `true` if both arguments are equal, instead of `false` as you do? – Daniel Langr Nov 02 '18 at 07:30
  • 2
    @zett42 [You don't have to](https://en.cppreference.com/w/cpp/language/operator_alternative) – Zereges Nov 02 '18 at 07:31
  • I define set like that ,std::set entSet; I try exchange false and true, it totally not work , do like this way, it partly works. –  Liu Nov 02 '18 at 07:36
  • Please, show us [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) then. Your code is not compilable. – Daniel Langr Nov 02 '18 at 07:42
  • @Liu, the second type parameter in `std::set` is the order relation (i.e., the comparator), not the equality predicate. In other words, you should not pass `equal4EntityTermSet` as the second parameter in `std::set`, otherwise you will get erroneous results. – Ilio Catallo Nov 02 '18 at 09:42

1 Answers1

2

std::set detects duplicates by means of the trichotomy law, which states that if !cmp(a, b) && !cmp(b, a) then eq(a, b), for some order relation cmp and some equivalence relation eq. If you want eq to stand for equal, you need to provide a order relation cmp that models a strict total ordering between TokenTerms. One such ordering is the lexicographical order, which can be readily achieved by way of std::tie. Here's a complete example:

#include <set>
#include <tuple>
#include <string>
#include <iostream>

typedef unsigned int uint32_t;

struct TokenTerm {
    std::string     value;
    std::string     type;
    uint32_t        start_pos;
    uint32_t        end_pos;
};

struct TokenTermCmp {
    bool operator()(TokenTerm const& x, TokenTerm const& y) const {
        return std::tie(x.value, x.type, x.start_pos, x.end_pos) < std::tie(y.value, y.type, y.start_pos, y.end_pos);
    }
};

int main() {
    std::set<TokenTerm, TokenTermCmp> tokens;
    tokens.insert({"value", "type", 0, 10});
    tokens.insert({"value", "type", 0, 10});

    for (auto&& token: tokens) 
        std::cout << token.value << ", "
                  << token.type << ", "
                  << token.start_pos << ", "         
                  << token.end_pos
                  << '\n';
}

In the above, despite the double insertion of the TokenTerm of value {"value", "type", 0, 10}, the set still comprises one single element. Hopefully, this should fix the problem.

Ilio Catallo
  • 3,152
  • 2
  • 22
  • 40
  • It is not work for me, I use a trick to solve this problem. by using a map , and first item string will concat ["type","value" ,...] and then ,compare them only by the string. not beautiful but useful. –  Liu Nov 02 '18 at 09:07
  • Before resorting to such a crude workaround, why don't you first try to understand which `TokenTerm` is inserted twice and use it to create a minimal working example? – Ilio Catallo Nov 02 '18 at 09:13
  • yes, you are right, I should do it, but after struggle with the wired problem. I just want to close the problem ... lazy me –  Liu Nov 02 '18 at 09:35