如何立即检查一组对是否有逗号?

How can I check, straight away, if a set of pairs have a commom number?

提问人:Nicholas Yamasaki 提问时间:10/2/2022 最后编辑:PabloNicholas Yamasaki 更新时间:10/2/2022 访问量:360

问:

假设我们有 4 对,例如

pair<int, int> P1(1, 2);
pair<int, int> P2(3, 1);
pair<int, int> P3(2, 1);
pair<int, int> P4(1, 5);

我怎样才能直接比较这 4 对并得出结论,它们都有共同点的数字 1?我只能想到两个两个比较,但这对很多配对来说都是很多工作......

是否有某些函数可以对任何给定的对集执行此操作?

C++ 列表 比较 std-pair

评论

0赞 Pablo 10/2/2022
请不要向标签发送垃圾邮件,这个问题与 无关,所以不要用 标记它。cc
0赞 Nathan Pierson 10/2/2022
您不必进行二次比较。请注意,如果所有对都有一些共同的数字 X,那么第一对中就有 X。而第一对中只有两个值。因此,您可以检查“是否每对都包含?”,然后您可以检查“是否每对都包含?”,如果这两个答案都不是“是”,那么您可以得出结论,所有对都没有共同的数字。P1.firstP1.second

答:

1赞 Peter 10/2/2022 #1

在您给出的示例代码中,您需要分别检查每一对(、 等)(例如 )。P1P2if (P1.first == 1 || P1.second == 1 || P2.first == 1 || <etc> )

如果您坚持拥有 P1,...P4 作为不同的变量,没有捷径可走,因为您已经定义了 、 、 ... 以一种在它们之间不强加逻辑或结构关系的方式。(例如,不能保证它们在机器内存中的位置 - 它们可能在一起,也可能在完全不相关的内存位置)。P1P2P4

但是有多个具有顺序名称的变量,例如 、 、 .....表示您需要使用原始数组(例如)或标准容器(例如)。如果您使用原始数组或标准容器来构建代码,则有一些选项。例如,原始数组;P1P2pair<int, int> P[4]vector<pair<int, int> > P

 std::pair<int, int> P[4];
  //  set the four elements of P
 bool has_one = false;
 for (int i = 0; has_one == false && i < 4; ++i)
     if (P[i].first == 1 || P[i].second == 1) has_one = true;

它可以很容易地扩展到任意数量的对,只要该数字在编译时是固定的。请记住,数组索引从零开始,而不是从 1 开始(即 存在于上述内容中,但不存在)。P[0]P[4]

这种代码的危险在于没有正确更新数字(例如,将 from 的元素数更改为 ,但忘记在循环中进行相同的更改)。P427

比起使用原始数组,更好的选择是使用标准容器 - 特别是如果你想用一组对做很多事情。如果在编译时对数是固定的,则可以将上述定义更改为使用标准容器。Parray

 std::array<std::pair<int, int>, 4> P;      // array is from standard header <array>
  //  assign the four elements of P (code omitted)

与使用原始数组相比,它提供了许多优势。

如果在编译时不知道对数(例如,该数是根据运行时读取的值计算的),则可以使用另一个标准容器,例如

// compute n as the number of elements
std::vector<std::pair<int, int> > P (n);

在所有情况下,原始数组(注意避免检查比数组更多的元素)和标准容器都可以在循环中使用。

但是,最好(因为它不太容易出错)避免 - 在可能的情况下 - 使用循环,而是使用 C++ 标准库提供的算法。例如(C++11 及更高版本),您可以执行以下操作

#include <algorithm>
#include <vector>

int main()
{
    // compute n as the number of elements  (code omitted)

    std::vector<std::pair<int, int>> P(n);

    // populate elements of P  (code omitted)

    auto check_if_one = [](std::pair<int, int> a)
                        {return a.first == 1 || a.second == 1;};

    bool has_one = (std::find_if(std::begin(P), std::end(P), check_if_one) != std::end(P));

}

这样做的优点是,代码始终正确地考虑 中的元素数。计算上述值的方法都是相同的,无论原始数组、a 、a 还是标准库中的任何其他容器。Phas_onePstd::arraystd::vector

2赞 Lautaro urtiaga 10/2/2022 #2

没有“内置”的帮助程序来检查所有货币对是否都包含某个数字,但这是一个相当容易的操作!

为此,您需要一个接收对列表的函数。

bool allPairsShareNumber(list<pair<int, int>> pairs, int number) {
    return all_of(pairs.begin(), pairs.end(), [&number](pair<int,int> pair){
        return pair.first == number || pair.second == number;
    });
}

然后你可以把列表传递给函数!

pair<int, int> P1(1, 2);
pair<int, int> P2(3, 1);
pair<int, int> P3(2, 1);
pair<int, int> P4(1, 5);

list<pair<int, int>> pairList = { P1, P2, P3, P4 };

bool doTheyAllContain1 = allPairsShareNumber(pairList, 1);

评论

0赞 Nathan Pierson 10/2/2022
需要一个列表,特别是作为要迭代的容器,这有点奇怪。但是,用提问者想要使用的任何容器替换它很容易,或者重写为一个需要开始和结束迭代器的模板。listallPairsShareNumber
0赞 Lautaro urtiaga 10/2/2022
是的,任何其他可迭代的结构就足够了,思想列表就足够简单了。