Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何通过STL容器中的子字符串删除元素_C++_Algorithm_Stl - Fatal编程技术网

C++ 如何通过STL容器中的子字符串删除元素

C++ 如何通过STL容器中的子字符串删除元素,c++,algorithm,stl,C++,Algorithm,Stl,我有一个对象向量(对象是术语节点,在其他字段中包含字符串字段和术语字符串) 经过一些处理和计算分数后,这些对象最终存储在一个TermNode指针向量中,例如 std::vector<TermNode *> termlist; 我试图做的是清理最终列表中的子字符串,这些子字符串也包含在术语列表中的短语中。例如,在上面的列表片段中,有短语'knowledge discovery',因此我想删除单个术语'knowledge'和'discovery',因为它们也在列表中,在这个上下文中是多

我有一个对象向量(对象是术语节点,在其他字段中包含字符串字段和术语字符串)

经过一些处理和计算分数后,这些对象最终存储在一个TermNode指针向量中,例如

std::vector<TermNode *> termlist;
我试图做的是清理最终列表中的子字符串,这些子字符串也包含在术语列表中的短语中。例如,在上面的列表片段中,有短语'knowledge discovery',因此我想删除单个术语'knowledge''discovery',因为它们也在列表中,在这个上下文中是多余的。我想保留包含单个术语的短语。我还考虑删除所有等于或少于3个字符的字符串。但这只是目前的一个想法

对于这个清理过程,我想用ReleVixIF/FiffyIF(使用新的C++ LAMBDAS)对一个类进行编码,在紧凑类中使用代码是很好的。 我真的不知道如何解决这个问题。问题是,我首先必须确定要删除哪些字符串,方法可能是设置一个标志作为删除标记。这意味着我必须预先处理这份名单。我必须找到单个术语和包含其中一个术语的短语。我认为这不是一项容易的任务,需要一些先进的算法。使用后缀树来识别子字符串

向量上的另一个循环和同一向量的一个副本可以用于清理。我正在寻找一种最有效的时间方式

我一直在玩弄这个想法或方向,比如在使用remove\u if/find\u if中显示的想法和在中使用的想法

所以问题基本上是,有没有一个聪明的方法来做到这一点,避免多个循环,我如何才能识别出要删除的单个术语?也许我真的错过了什么,但可能有人在那里,给了我一个很好的暗示

谢谢你的想法

更新

我按照如下建议的方式实施了删除冗余单术语的工作:

/**
 * Functor gets the term of each TermNode object, looks if term string
 * contains spaces (ie. term is a phrase), splits phrase by spaces and finally
 * stores thes term tokens into a set. Only term higher than a score of 
 * 'skipAtWeight" are taken tinto account.
 */
struct findPhrasesAndSplitIntoTokens {
private:
    set<wstring> tokens;
    double skipAtWeight;

public:
    findPhrasesAndSplitIntoTokens(const double skipAtWeight)
    : skipAtWeight(skipAtWeight) {
    }

    /**
     * Implements operator()
     */
    void operator()(const TermNode * tn) {
        // --- skip all terms lower skipAtWeight
        if (tn->getWeight() < skipAtWeight)
            return;

        // --- get term
        wstring term = tn->getTerm();
        // --- iterate over term, check for spaces (if this term is a phrase)
        for (unsigned int i = 0; i < term.length(); i++) {
            if (isspace(term.at(i))) {
if (0) {
                wcout << "input term=" << term << endl;
}
                // --- simply tokenze term by space and store tokens into 
                // --- the tokens set
                // --- TODO: check if this really is UTF-8 aware, esp. for
                // --- strings containing umlauts, etc  !!
                wistringstream iss(term);
                copy(istream_iterator<wstring,
                        wchar_t, std::char_traits<wchar_t> >(iss),
                    istream_iterator<wstring,
                        wchar_t, std::char_traits<wchar_t> >(),
                    inserter(tokens, tokens.begin()));
if (0) {
                wcout << "size of token set=" << tokens.size() << endl;
                for_each(tokens.begin(), tokens.end(), printSingleToken());
}
            }
        }
    }

    /**
     * return set of extracted tokens
     */
    set<wstring> getTokens() const {
        return tokens;
    }
};

/**
 * Functor to find terms in tokens set
 */
class removeTermIfInPhraseTokensSet {
private:
    set<wstring> tokens;

public:
    removeTermIfInPhraseTokensSet(const set<wstring>& termTokens)
    : tokens(termTokens) {
    }

    /**
     * Implements operator()
     */
    bool operator()(const TermNode * tn) const {
        if (tokens.find(tn->getTerm()) != tokens.end()) {
            return true;
        }
        return false;
    }
};

...

findPhrasesAndSplitIntoTokens objPhraseTokens(6.5);
objPhraseTokens = std::for_each(
    termList.begin(), termList.end(), objPhraseTokens);
set<wstring> tokens = objPhraseTokens.getTokens();
wcout << "size of tokens set=" << tokens.size() << endl;
for_each(tokens.begin(), tokens.end(), printSingleToken());

// --- remove all extracted single tokens from the final terms list
// --- of similar search terms 
removeTermIfInPhraseTokensSet removeTermIfFound(tokens);
termList.erase(
    remove_if(
        termList.begin(), termList.end(), removeTermIfFound),
    termList.end()
);

for (vector<TermNode *>::const_iterator tl_iter = termList.begin();
      tl_iter != termList.end(); tl_iter++) {
    wcout << "DEBUG: '" << (*tl_iter)->getTerm() << "' term weight=" << (*tl_iter)->getNormalizedWeight() << endl;
    if ((*tl_iter)->getNormalizedWeight() <= 6.5) break;
}

...
/**
*Functor获取每个TermNode对象的术语,如果术语字符串
*包含空格(即术语是短语),按空格拆分短语,最后
*将这些术语标记存储到集合中。唯一一项得分高于
*“skipAtWeight”被考虑在内。
*/
结构findPhrasesAndSplitIntoTokens{
私人:
设置代币;
双倍重量;
公众:
findPhrasesAndSplitIntoTokens(常量双skipAtWeight)
:skipAtWeight(skipAtWeight){
}
/**
*实现运算符()
*/
void运算符()(常量TermNode*tn){
//---跳过所有术语,降低SkipPatWeight
如果(tn->getWeight()getTerm();
//---迭代术语,检查空格(如果该术语是短语)
for(无符号整数i=0;iwcout我可以建议你这样使用这个成语:

struct YourConditionFunctor {
    bool operator()(TermNode* term) {
        if (/* you have to remove term */) {
           delete term;
           return true;
        }
        return false;
    }
};
然后写:

termlist.erase(
    remove_if(
        termlist.begin(),
        termlist.end(), 
        YourConditionFunctor()
    ), 
    termlist.end()
);

您需要做的是,首先遍历列表,并将所有多单词值拆分为单个单词。如果您允许使用Unicode,这意味着您将需要类似于ICU的BreakIterators的东西,否则您可以使用简单的标点/空格拆分。当每个字符串拆分为其组成单词时,然后使用哈希映射来ep当前所有单词的列表。当您达到一个多单词值时,您可以检查是否已找到该单词。这应该是识别重复单词的最简单方法。

您的问题标题似乎有点误导……这不是向量问题,而是文本处理问题。一旦您识别了子字符串,purgi从向量中删除它们是很简单的,特别是当只有400个条目时。为什么不使用
向量
的智能指针指向
TermNode
对象?这样,你就不必
删除
查找
操作后返回的指针了?我很想按与术语长度相反的顺序对向量进行排序。Itera在向量上,将每个术语拆分为单独的单词,并将这些单词放入
std::set
。如果单词已经存在于集合中,则将该术语标记为需要删除,然后担心清除向量。哦,如果您使用
std::list
而不是向量,则会得到固定时间的插入和删除,并且您可以进行反编译在不使迭代器失效的情况下删除项目。您真的需要对向量中的项目进行随机访问,还是只需要能够遍历它?@Rook:从容器中高效方便地删除项目很难衡量。由于内存缓存行为,
向量
通常优于
列表
即使是“中间”操作,也要少量",小到几百或几千件物品。大O复杂性的问题是,它使理论复杂性达到极限,并且幸福地忽略了不变的因素,以及许多人一开始只处理小收藏的事实。不幸的是,这是我担心的相当容易的部分。p问题(与标题所暗示的不同)正在识别要删除的术语。此外,我发现实际上
删除谓词中的项是一种非常糟糕的做法。这违反了谓词的所有常规用法,通常不会修改它们被调用的对象,听起来像是一种灾难。是的,我必须同意Matthieu的观点,如何做到这一点在我的问题文本中所述的问题中。我认为stackoverflow的一系列答案说明了如何使用这个术语。我的问题更多的是如何清理术语,以及如何选择正确的容器来使用上面的习惯用法。这
struct YourConditionFunctor {
    bool operator()(TermNode* term) {
        if (/* you have to remove term */) {
           delete term;
           return true;
        }
        return false;
    }
};
termlist.erase(
    remove_if(
        termlist.begin(),
        termlist.end(), 
        YourConditionFunctor()
    ), 
    termlist.end()
);