【问题标题】:Removing elements of a string vector with certain char requirements删除具有特定字符要求的字符串向量的元素
【发布时间】:2018-08-27 00:16:07
【问题描述】:

我目前正在编写一个程序,该程序由一个字符串向量组成,该向量充满了在同一位置具有特定字母的单词。

例如,我的向量可能如下所示:

vector<string> v = { "CRYPT", "CYSTS", "WRYLY", "TRYST" };

这个想法是猜测一个字母,即在这种情况下为“Y”,程序选择向量中的第一个字符串,遍历字符串向量并保留与第一个单词相同位置的 Y在向量中。在这种情况下,程序会选择“CRYPT”。现在,我需要程序遍历字符串向量并删除与第一个单词“CRYPT”相比在某个额外位置具有该字母重复的任何单词,同时保留具有“Y”的单词在相同的确切位置除了第一个单词 place 之外,其他地方没有其他“Y”。因此,在删除任何额外的重复项并保持其他具有相同位置的字母的单词之后,我需要向量的输出看起来像这样。

vector<string> v = { "CRYPT", "TRYST" };

我正在考虑遍历向量并遍历每个字符串以遍历每个字符并进行检查,但是我无法在遍历向量时从向量中删除元素,否则会导致问题。也许将 remove_if 用于向量,但不确定如何编写谓词。任何帮助表示赞赏!谢谢!

【问题讨论】:

  • 谓词只做检查。你打算如何在循环中检查它? (忽略移除的困难,专注于检查)。
  • 何不尝试一下,等有实际问题再回来?
  • 看看copy_if。
  • 在我看来,这与其说是一个 c++ 问题,不如说它正在制定你想要的东西。 remove_if 的想法是正确的,但是您没有在 c++ 术语中指定接受哪些字符串。
  • 可能是 std::find_if 获取第一个元素,然后是 std::remove_if 删除后续元素?

标签: c++ string vector char


【解决方案1】:

一种方法是定义一个仿函数来评估给定字符串是否符合复制到结果向量的标准。然后将仿函数与copy_if 一起使用。

类似:

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

struct do_copy
{
    do_copy(char m) : match(m) {}
    char match;
    size_t pos;
    bool found {false};

    bool operator()(const std::string& s)
    {
        if (found)
        {
            return s.size() > pos && 
                   s[pos] == match && 
                   std::count(s.begin(), s.end(), match) == 1;
        }

        for (int p = 0; p < s.size(); ++p)
        {
            if (s[p] == match)
            {
                pos = p;
                found = true;
                return true;
            }
        }
        return false;
    }
};

int main() {
    std::vector<std::string> v = { "CRYPT", "CYSTS", "WRYLY", "TRYST" };
    std::vector<std::string> r;
    char guess = 'Y';

    std::copy_if(v.begin(), 
                 v.end(), 
                 std::back_inserter(r), 
                 do_copy(guess));

    // Print the result
    std::cout << r.size() << " elements found:" << std::endl;
    for (auto& s : r) 
    {
        std::cout << s << std::endl;
    }

    return 0;
}

输出:

2 elements found:
CRYPT
TRYST

【讨论】:

    【解决方案2】:

    让我们从你的向量开始,然后是猜测的字符和你的“主要”字符串

    vector<string> v = { "CRYPT", "CYSTS", "WRYLY", "TRYST" };
    string mainStr = v[0];
    char guessed = 'Y';
    

    正如您所说,如果它们不符合我们的规则,我们需要遍历所有字符串并删除它们。所以就这样做吧,但我们不会用“for_each”进行迭代,我们将使用简单的循环

    for (size_t i = 1; i < v.size(); ++i) {
        for (size_t j = 0; j < v[i].size(); ++j) {
            if (v[i][j] == guessed && (j >= mainStr.size() || mainStr[j] != guessed) 
               || j < mainStr.size() && mainStr[j] == guessed && v[i][j] != guessed) {
                v.erase(find(v.begin(), v.end(), v[i]));
                --i;
                break;
            }
        }
    }
    

    在内部循环中,如您所见,当我们删除这样一个我们不想在集合中看到的字符串时,我们只是用我们的“迭代器”退后一步,所以我们不会破坏任何向量条件我们可以继续迭代字符串。

    最后你可以简单地看到,我们做得对

    for (auto& str : v) {
        cout << str << '\n';
    }
    

    【讨论】:

    • 当向量包含没有任何Y 的单词时,这将无法正常工作。相反,首先检查长度匹配,然后检查两个单词都有guessed或者它们都没有guessed的每个位置:if(v[i].size() != mainStr[i].size() || (v[i][j] == guessed) != (mainStr[j] == guessed)) { ... }
    • 是的,确实,我们也应该在 mainStr 中检查 Y,但是为什么我们不应该保留长度不匹配的单词呢?
    • 啊,如果你想支持长度与mainStr不同的单词,那么确实可以支持,但是原问题并没有具体说明这种情况下该怎么做。
    猜你喜欢
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    相关资源
    最近更新 更多