合并文本文件不同行中的重复项

时间:2018-10-16 19:10:17

标签: c++ arrays file-io

我有一个文本文件,其中行上的第一个数字是图形的节点号,第二个数字是连接到第一个的节点的号。第三个数字是边缘的重量。

这是一个示例案例,文件中的两行包含权重为.5的3和5:

    1 3 0.5
    3 5 0.5
    3 6 0.5
    3 5 0.5
    6 8 0.5
    4 6 1

我希望能够将它们合并为仅包含3和5的连接的一行,但将权重更新为它们的权重之和(在本例中为1)。然后应删除重复的行。

所以我想检查重复的节点对,如果我发现重复的节点对总和总重,然后为该对更新一行以具有正确的总权重,然后用那些删除所有其他行节点。

我为Edges创建了一个结构:

struct Edge {
    int c1, c2;
    float weight;
};

我已阅读文件并将其全部放入此结构中:

if (updateGraph.is_open()) {
    string data[3];
    Edge e;

    while (getline(updateGraph, stri)) {
        stringstream in(stri);
        int i = 0;
        while (in.good() && i < 3) {
            in >> data[i];
            i++;
        }
        e.c1 = atoi(data[0].c_str());
        e.c2 = atoi(data[1].c_str());
        e.weight = atof(data[2].c_str());
        cout << e.c1 << " " << e.c2 << " " << e.weight << endl;
    }
}

但是现在我不确定如何比较它们以查看是否有任何边具有相同的c1和c2。我该怎么办?

1 个答案:

答案 0 :(得分:0)

  

我已经阅读了文件并将它们全部放入此结构中:[...]但是现在我不确定如何比较它们以查看是否有任何边具有相同的c1和c2。

从逻辑上讲,您知道您需要做的不仅仅是读取边缘并打印出来。您的程序必须保留到目前为止所见边缘的一些内存。例如,可能必须将第一行的边缘与最后一行的边缘合并。

  

我该怎么做?

没有单一的“正确”方法来做到这一点。但是,如果您要尝试使自己的类类似于您定义的Edge结构,那么您将不得不编写更多代码。例如,要使用std::set集合,您将需要a comparison operator(请注意,C ++甚至没有提供默认的equality operator。)

如果您避免创建自定义结构,C ++可以为您做更多的工作。取而代之的是,您可以将状态存储为std::map到浮动权重为std::tuple<int, int>。元组已经知道如何进行比较。这种思维方式将边缘的概念与重量的概念区分开来。

在不为您编写代码的情况下,这里展示了您正在寻找的那种能力...通过“常规” C ++方式完成的:

#include <iostream>
#include <map>
#include <tuple>

typedef std::tuple<int, int> Edge;
std::map<Edge, float> mapEdgeToWeight;

int main() {
    Edge e1 {3, 5}; float w1 = 0.5;
    Edge e2 {3, 5}; float w2 = 0.5;

    auto it1 = mapEdgeToWeight.find(e1);
    if (it1 != mapEdgeToWeight.end())
        std::cout << "Existing {3, 5} edge (won't happen)\n";
    else {
        std::cout << "First {3, 5} edge (this is first)\n";
        mapEdgeToWeight[e1] = w1;
    }

    auto it2 = mapEdgeToWeight.find(e2);
    if (it2 != mapEdgeToWeight.end()) {
        std::cout << "Existing {3, 5} edge (now happens)\n";
        it2->second += w2; // first is edge, second is weight
    }
    else
        std::cout << "First {3, 5} edge (it isn't first!)\n";

    for (auto &pair : mapEdgeToWeight)
        std::cout << "Edge: "
            << std::get<0>(pair.first) << ","
            << std::get<1>(pair.first)
            << " Weight: " << pair.second << "\n";
}

正如评论中所建议的那样,与考虑在现有文件中“合并行”相比,您最好考虑在...处理过程中读取文件,然后写出新文件。 / p>

如果您是C ++的新手,那么您有很多东西要学习,而不知道如何编写某些东西并问“我将如何做”的问题就可以进入StackOverflow。肯定是一个艰难的方法。我建议您通过编写有关该主题的书来打下坚实的基础。即使您要使用自己的文字来上课,也不要害怕在这里拿起一本不错的现代书来进行猜测:

The Definitive C++ Book Guide and List

但是现在,通过研究有关如何使用std :: map和std :: tuple的教程,您至少知道一个可以开始的地方。