C ++使用第三个序列作为标准检查两个序列是否相等
C++ check if two sequences are equal using a 3rd sequence as criteria
我需要检查两个给定序列是否相等,但如果我发现不匹配的元素,我需要检查第三个序列(与其他两个序列大小相同)是否可以忽略。
我知道我可以写一个简单的算法来解决这个问题,但我想知道是否有任何类似 C++ 的风格来解决这个问题,使用标准算法。
示例:
A = [1, 2, 3, 4, 5, 6]
B = [1, 2, 3, A, 5, 6]
M = [true, true, true, false, true, true]
N = [true, true, true, true, true, true]
bool equal1 = the_equal(begin_A, end_A, begin_B, begin_M); // Should return true, even if '4' is different from 'A' since in the same position of the found mismatch, in the M sequence, we have a false that indicates that position should be ignored.
bool equal2 = the_equal(begin_A, end_A, begin_B, begin_N); // Should return false, since '4' is different from 'A' and we have a true in sequence N for that position.
这可以通过类似的方式解决:
template<I1, I2, I3> // iterators
bool the_equal(I1 first1, I1 last1, I2 first2, I3 first3) {
while (first1 != last1) {
if (*first1 != *first2 && *first3 != false)
return false;
++first1; ++first2; ++first3;
}
return true;
}
编辑:由于工具链的限制,我忘了说我需要在 c++98 中解决这个问题:(
虽然std::equal
接近了,但不清楚是否可以直接使用。我认为您的代码非常好。我可能会将其重写为
template<I1, I2, I3> // iterators
bool equal_with_mask(I1 first1, I1 last1, I2 first2, I3 first3) {
for (; first1 != last1; ++first1, ++first2, ++first3) {
if (*first3 && (*first1 != *first2)) {
return false;
}
}
return true;
}
如果(不)相等比较很重,那么首先检查掩码可能会很好。
小知识:第三个序列 (first3
) 就像在某些硬件设备中使用的掩码,例如三元内容可寻址存储器 (TCAM)。
您可以创建一个(可变的)仿函数:
template <typename IT>
struct CmpWithMask
{
CmpWithMask(IT it) : it(it) {}
template <typename LHS, typename RHS>
bool operator () (const LHS& lhs, const RHS& rhs) {
return !*it++ || lhs == rhs;
}
IT it;
};
template <typename IT>
CmpWithMask<IT> MakeCmpWithMask(IT it) { return CmpWithMask<IT>{it}; }
然后,使用std::equal
:
std::cout << std::equal(A.begin(), A.end(),
B.begin(),
MakeCmpWithMask(M.begin())) << std::endl;
std::cout << std::equal(A.begin(), A.end(),
B.begin(),
MakeCmpWithMask(N.begin())) << std::endl;
我也觉得你的代码很好。您可以使用标准函数之一,但恕我直言,并不总是建议这样做,因为它会降低代码的可读性。最好的解决方案是您可以阅读的解决方案。但是,这里有一个解决方案(许多可能的实现之一)使用 std::mismatch :
template<typename I1, typename I2, typename I3> // iterators
bool the_equal2(I1 first1, I1 last1, I2 first2, I3 first3) {
auto p = std::mismatch(first1, last1, first2);
if(p.first != last1)
return (!first3[p.first - first1] ? true : the_equal2(p.first+1, last1, p.second+1, first3));
return false;
}
请参阅 here 实际操作,并注意,未检查错误...
但是它看起来比 发布的例子更好吗?使用递归和 auto p
,如果您不知道什么不匹配 returns(std::pair<I1, I2>
),您甚至必须查找 p
可能是什么类型?您甚至可以通过使用一些 iterator_traits 或奇特的 find_if/equal/mismatch 组合来改进它,以摆脱递归并使其更加不可读。
我需要检查两个给定序列是否相等,但如果我发现不匹配的元素,我需要检查第三个序列(与其他两个序列大小相同)是否可以忽略。
我知道我可以写一个简单的算法来解决这个问题,但我想知道是否有任何类似 C++ 的风格来解决这个问题,使用标准算法。
示例:
A = [1, 2, 3, 4, 5, 6]
B = [1, 2, 3, A, 5, 6]
M = [true, true, true, false, true, true]
N = [true, true, true, true, true, true]
bool equal1 = the_equal(begin_A, end_A, begin_B, begin_M); // Should return true, even if '4' is different from 'A' since in the same position of the found mismatch, in the M sequence, we have a false that indicates that position should be ignored.
bool equal2 = the_equal(begin_A, end_A, begin_B, begin_N); // Should return false, since '4' is different from 'A' and we have a true in sequence N for that position.
这可以通过类似的方式解决:
template<I1, I2, I3> // iterators
bool the_equal(I1 first1, I1 last1, I2 first2, I3 first3) {
while (first1 != last1) {
if (*first1 != *first2 && *first3 != false)
return false;
++first1; ++first2; ++first3;
}
return true;
}
编辑:由于工具链的限制,我忘了说我需要在 c++98 中解决这个问题:(
虽然std::equal
接近了,但不清楚是否可以直接使用。我认为您的代码非常好。我可能会将其重写为
template<I1, I2, I3> // iterators
bool equal_with_mask(I1 first1, I1 last1, I2 first2, I3 first3) {
for (; first1 != last1; ++first1, ++first2, ++first3) {
if (*first3 && (*first1 != *first2)) {
return false;
}
}
return true;
}
如果(不)相等比较很重,那么首先检查掩码可能会很好。
小知识:第三个序列 (first3
) 就像在某些硬件设备中使用的掩码,例如三元内容可寻址存储器 (TCAM)。
您可以创建一个(可变的)仿函数:
template <typename IT>
struct CmpWithMask
{
CmpWithMask(IT it) : it(it) {}
template <typename LHS, typename RHS>
bool operator () (const LHS& lhs, const RHS& rhs) {
return !*it++ || lhs == rhs;
}
IT it;
};
template <typename IT>
CmpWithMask<IT> MakeCmpWithMask(IT it) { return CmpWithMask<IT>{it}; }
然后,使用std::equal
:
std::cout << std::equal(A.begin(), A.end(),
B.begin(),
MakeCmpWithMask(M.begin())) << std::endl;
std::cout << std::equal(A.begin(), A.end(),
B.begin(),
MakeCmpWithMask(N.begin())) << std::endl;
我也觉得你的代码很好。您可以使用标准函数之一,但恕我直言,并不总是建议这样做,因为它会降低代码的可读性。最好的解决方案是您可以阅读的解决方案。但是,这里有一个解决方案(许多可能的实现之一)使用 std::mismatch :
template<typename I1, typename I2, typename I3> // iterators
bool the_equal2(I1 first1, I1 last1, I2 first2, I3 first3) {
auto p = std::mismatch(first1, last1, first2);
if(p.first != last1)
return (!first3[p.first - first1] ? true : the_equal2(p.first+1, last1, p.second+1, first3));
return false;
}
请参阅 here 实际操作,并注意,未检查错误...
但是它看起来比 auto p
,如果您不知道什么不匹配 returns(std::pair<I1, I2>
),您甚至必须查找 p
可能是什么类型?您甚至可以通过使用一些 iterator_traits 或奇特的 find_if/equal/mismatch 组合来改进它,以摆脱递归并使其更加不可读。