C ++从字符串向量中删除子字符串

时间:2019-07-23 09:59:36

标签: c++ stl

给出一个字符串向量:

    std::vector<std::string> contents {"right", "sun is shining", "high hopes", "I wish you were here", "shining", "do it right"};

我想删除所有属于其他子字符串的元素。在此示例中,“ right”和“ shining”是要删除的。

我正在遍历向量和每个元素,进行另一个循环以检查是否有包含它的其他元素。 请参阅下面的实际代码。

我想知道是否有更好的方法。 (使用stl算法?)

    std::vector<std::string> contents{"right", "sun is shining",
    "high hopes", "I wish you were here", "shining", "do it right"};
    std::vector<std::string> result;
    for (size_t i = 0, j = 0; i < contents.size(); ++i)
    {
        for (j = 0; j < contents.size(); ++j)
        {
            if (i != j && boost::algorithm::contains(contents[j], contents[i]))
            {
                std::cout << "[" << contents[i] << "] contained in [" << contents[j] << "]" <<std::endl;
                break;
            }
        }
        if (j == contents.size())
        {
            std::cout << "[" << contents[i] << "] not contained in any element" << std::endl;
            result.push_back(contents[i]);
        }
    }

预期结果将是: {“阳光明媚”,“充满希望”,“我希望你在这里”,“做对了”};

1 个答案:

答案 0 :(得分:0)

嗯。好还是不好。

我认为您的解决方案可以。为什么您使用升压,我不明白。这里不需要。这项任务很简单。

共性始终为n * n(不完全。我们不将字符串与istself进行比较)

我准备了3种选择。

版本1正在使用std::algorithm

没人会理解它,它看起来像是混淆的代码。

版本2与版本1完全相同。我刚刚添加了许多换行符和注释。人们可以从中学到东西,并且可能会理解。但实际上,这里也有很多声明。

我认为第3版是最合理的方法。与您相似。仅使用基于的范围。而且没有助力。简单的C ++语句。

请参阅:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

void version1()
{
    // Source data
    std::vector<std::string> contents{ "right", "sun is shining", "high hopes", "I wish you were here", "shining", "do it right" };
    // print filtered data to std::out 
    std::copy_if(contents.begin(), contents.end(), std::ostream_iterator<std::string>(std::cout, "\n"),
        [&contents](std::string & s1) { return std::find_if(contents.begin(), contents.end(), [&s1](std::string & s2) {
            return (s1 != s2) && (s2.find(s1) != std::string::npos); }) == contents.end(); });

}

void version2()
{
    // Source data
    std::vector<std::string> contents{ "right", "sun is shining", "high hopes", "I wish you were here", "shining", "do it right" };

    // Copy data to standard out only if
    std::copy_if
    (
        contents.begin(),                   // Evaluate from the begin of the source string 
        contents.end(),                     // To the end of the source string
        std::ostream_iterator<std::string>(std::cout, "\n"),    // Display found results on console
        [&contents](std::string & s1)       // The lambda to decide, if we will copy or not
        {   
            return std::find_if             // We will copy only, if we do not find a substring
            (
                contents.begin(),           // We compare verything with everything
                contents.end(),             // Every word, from the source string with every other word
                [&s1](std::string & s2) 
                {
                    return (s1 != s2) &&    // But not the same string with itself
                           (s2.find(s1) != std::string::npos);  // Check, if it is a substring
                }
            ) == contents.end();            // If we cannot find a substring, then we copy the data to the output
        }
    );
}

void version3()
{
    // Source data
    std::vector<std::string> contents{ "right", "sun is shining", "high hopes", "I wish you were here", "shining", "do it right" };

    // Iterate over all strings in source vector
    for (const std::string& s1 : contents) {

        // Initially we have not found a substring
        bool subStringFound{ false };

        // Now compare every string in vector with every other string
        for (const std::string& s2 : contents) {
            // If one is a real substring of the other
            if ((s1 != s2) && (s2.find(s1) != std::string::npos)) {
                // Then we found something
                subStringFound = true;
            }
        }
        // If we did not find a substring
        if (!subStringFound)
            // Then show it
            std::cout << s1 << '\n';
    }
}

int main()
{
    std::cout << "\n\nVersion 1\n\n";
    version1();
    std::cout << "\n\nVersion 2\n\n";
    version2();
    std::cout << "\n\nVersion 3\n\n";
    version3();

    return 0;
}