c++ - 从文件中删除重复的反向行时出现问题

标签 c++ visual-studio

我有一个包含以下几行的文件,

connection list
current check OK

connect "A" to "B"
connect "A" to "C"
connect "A" to "D"
connect "C" to "A"
connect "A" to "E"

这里将“C”连接到“A”将“A”连接到“C”的反向连接 要求是去掉重复的反向连接。

我是 C++ 和 vector 的新手。我尝试使用以下内容:

首先,我采用了 2 个字符串 con1 和 con2 的结构:connectPair 然后我获取了结构的 vector

现在,我将文件行保存到 vector 中:rawFileLines 我正在尝试对 rawFileLines 进行操作以查找连接组件。

我将连接组件存储到另一个 vector :

这是我的代码:

typedef struct {
    std::string con1;
    std::string con2;
} ConnectPair;

void RemoveReversePairs(std::string inputFile) {
    std::vector<std::string> fileData;
    std::string line, scan, token1, token2;
    std::size_t tokenLeft, tokenRight, maxLines, lineNumber = 0, pos = 0;
    std::size_t found = 0, storeCount = 0;
    
    std::vector<std::string> rawFileLines;
    
    ConnectPair connectPair = {};
    std::vector<ConnectPair> values;
    


    std::ifstream source(inputFile.c_str());
    while (std::getline(source, line)) {
        rawFileLines.push_back(line);
    }
    source.close();
    maxLines = rawFileLines.size();

    for (size_t i = 0; i < maxLines; i++) {
        line = rawFileLines[i];
        pos = 0;
        scan = "\"";
        found = 0;

        while (found < 2) /*line.find(scan, pos) != std::string::npos*/ {
            tokenLeft = line.find(scan, pos);
            tokenRight = line.find(scan, tokenLeft + 1);

            if ((tokenLeft != std::string::npos) && (tokenRight != std::string::npos)) {
                found++;
                if (found == 1) {
                    connectPair.con1 = line.substr(tokenLeft + 1, (tokenRight - tokenLeft) - 1);
                }
                else if (found == 2) {
                    connectPair.con2 = line.substr(tokenLeft + 1, (tokenRight - tokenLeft) - 1);
                    values.push_back(connectPair);
                    storeCount++;
                }
                pos = tokenRight + 1;
            }
            else {
                connectPair.con1 = "++";
                connectPair.con2 = "++";
                values.push_back(connectPair);

                fileData.push_back(line);
                break;
            }
        }
    }

现在,我无法比较连接。请建议我如何继续。

谢谢。

最佳答案

将代码留在连接中读取,正如您在评论中提到的那样,这对您有用,请考虑使用算法 header 的 find_if 的 STL 解决方案以及 lambda。

为了简单起见,我有一个 std::vector<std::pair<std::string, std::string>>填充了您的示例连接数据。

我使用循环来打印它,以确保数据符合我的预期。该循环利用 destructuring删除很多烦人的样板文件。

然后才是解决方案的核心内容。我们使用显式迭代器来循环 vector ,使用 std::find_if检查 vector 的其余部分是否相同或反转时相同的连接。如果std::find_if返回结束迭代器,它没有找到任何东西,我们可以将该对推回 map2 vector 。如果 vector 的其余部分中确实存在等价项,则当前对不会被插入 map2 vector 。

在 lambda 中,捕获当前的 iter 非常重要。所以我们可以将它与其余部分进行比较(由 lambda b 的参数表示)。

[&iter](auto b) {
    return (iter->first == b.first  && iter->second == b.second) ||
           (iter->first == b.second && iter->second == b.first );
}
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

int main() {
    std::vector<std::pair<std::string, std::string>> map, map2;

    map.push_back({"A", "B"});
    map.push_back({"A", "C"});
    map.push_back({"A", "D"});
    map.push_back({"C", "A"});
    map.push_back({"A", "E"});

    std::cout << "Before:" << std::endl;

    for (auto &[k, v] : map) {
        std::cout << k << " -> " << v << std::endl;
    }

    auto end = map.end();

    for (auto iter = map.begin(); iter != end; iter++) {
        if (std::find_if(iter + 1, end,
                         [&iter](auto b) {
                             return (iter->first == b.first  && iter->second == b.second) ||
                                    (iter->first == b.second && iter->second == b.first );
                         }) == end) {
            map2.push_back(*iter);
        }
    }

    std::cout << "After: " << std::endl;

    for (auto &[k, v] : map2) {
        std::cout << k << " -> " << v << std::endl;
    }
}

结果:

Before:
A -> B
A -> C
A -> D
C -> A
A -> E
After:
A -> B
A -> D
C -> A
A -> E

更好

在考虑了我之前的示例之后,我意识到如果我们使用相同的比较逻辑(lambda 不变)来检查每个连接是否已存在于 map2 中,事情会更简单。 .

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

int main() {
    std::vector<std::pair<std::string, std::string>> map, map2;

    map.push_back({"A", "B"});
    map.push_back({"A", "C"});
    map.push_back({"A", "D"});
    map.push_back({"C", "A"});
    map.push_back({"A", "E"});

    std::cout << "Before:" << std::endl;

    for (auto &[k, v] : map) {
        std::cout << k << " -> " << v << std::endl;
    }

    auto end = map.end();

    for (auto iter = map.begin(); iter != end; iter++) {
        if (std::find_if(map2.begin(), map2.end(),
                         [&iter](auto b) {
                             return (iter->first == b.first  && iter->second == b.second) ||
                                    (iter->first == b.second && iter->second == b.first );
                         }) == map2.end()) {
            map2.push_back(*iter);
        }
    }

    std::cout << "After: " << std::endl;

    for (auto &[k, v] : map2) {
        std::cout << k << " -> " << v << std::endl;
    }
}

这样做的另一个好处是,我们现在获得 map2 中的“重复项”的第一个而不是最后

Before:
A -> B
A -> C
A -> D
C -> A
A -> E
After:
A -> B
A -> C
A -> D
A -> E

关于c++ - 从文件中删除重复的反向行时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69476010/

相关文章:

c++ - 将 boost::asio io_service 用于具有周期性任务的线程池?

c++ - outFile C++ 不写入输出文本

c++ - MinGW 作为可靠的 64 位 GCC 编译器

c# - 如何打包和部署带有符号和源代码的 NuGet 包,以便调试器可以使用该源代码?

visual-studio - 为什么我不应该使用/optimize 开关来编译我的 C# 代码?

c++ - "template"消歧器是 c++11。 VS2008 编译器有机会吗?

C++ 可变参数模板基础

asp.net - 分阶段部署到 Azure 网站时缺少 DLL

c++ - 将 .rdata 和 .data 部分合并到文本部分

c++ - VS C++ 2008 : Modifying Output text?