【问题标题】:Compare smaller vector to bigger to check if it differs at the end of smaller将较小的向量与较大的向量进行比较,以检查它是否在较小的末尾有所不同
【发布时间】:2019-05-20 17:43:09
【问题描述】:

我们有两个大小取决于运行时的向量,需要检查它们是否相等 - 只有在较小大小的向量结束后才会有不同的元素。我使用了 std::equal 但问题是我需要首先找到哪个向量较小,这会导致额外的代码行:

#include <vector>
#include <iostream>

int main()
{
  std::vector<int> a(1000, 3);
  std::vector<int> a1(100, 3);

  if(a.size() > a1.size())
  {
    if(std::equal(a1.begin(), a1.end(), a.begin()))
    {
      std::cout << "Same a gt a1" << std::endl;
    }
  }

  if(a1.size() > a.size())
  {
    if(std::equal(a.begin(), a.end(), a1.begin()))
    {
      std::cout << "Same a1 gt a" << std::endl;
    }
  }

  if(a1.size() == a.size())
  {
    if(std::equal(a.begin(), a.end(), a1.begin()))
    {
       std::cout << "Same a = a1" << std::endl;
    }
  }
}

可以改进比较两个向量或仅在较小向量末尾不同的代码吗?

【问题讨论】:

  • 仅 C++11?没有 C++14 吗?
  • 如果你没有实际问题(比如你当前的代码不满足性能要求,不一定是bug),只是想要代码审查,那么有codereview.stackexchange.com

标签: c++ c++11 vector size


【解决方案1】:

从 C++14 开始,您可以使用 std::mismatch 并检查返回的迭代器对与每个范围的末尾:

auto it = std::mismatch(a.begin(), a.end(), a1.begin(), a1.end());
if (it.first == a.end() || it.second == a1.end()) {
    // Equality
}

您还可以了解元素从哪里开始不同,如果没有,则更大的向量在哪一点更大(您不想比较的子范围的开始)。

【讨论】:

  • OP 在单个算法中想要的确切语义信息。 +1
  • 非常好。我不知道这个算法存在。 +1
【解决方案2】:

如果您事先计算出较小的尺寸,您只需调用一次std::equal。我会像这样重构代码:

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

int main()
{
    std::vector<int> a(1000, 3);
    std::vector<int> a1(100, 3);

    if (std::equal(a1.begin(), a1.begin() + std::min(a.size(), a1.size()), a.begin())) 
    {
        std::cout << "Same" << std::endl;
    }
    return 0;
}

如果您需要保留关于哪个向量更大的第二个信息,您可以这样实现,例如:

std::cout << "Same " << ((a.size() == a1.size())? "a = a1" : ((a.size() > a1.size())? "a gt a1" : "a1 gt a")) << std::endl;

【讨论】:

  • 我建议使用const auto size = std::min(a.size(), a1.size());。这也不会执行无符号到有符号的转换。
  • 好主意,已将其添加到帖子中。
  • 以上不包括第二条信息,例如:如果一个向量比另一个长,用户正在区分。
  • 也可以通过if (std::equal(a1.begin(), a1.begin() + std::min(a.size(), a1.size()), a.begin())) ...来消除变量size
【解决方案3】:

这是一个纯 C++11 解决方案,适用于任何顺序容器(例如 std::vectorstd::liststd::deque)。它使用自定义返回类型,因为您在原始 sn-ps 中显示的比较类型携带的信息比简单的布尔值所能包含的更多。

enum class CombinedCompareResult {
   NotEqual, EqualAndFirstLarger, EqualAndSecondLarger, EqualIncludingSize
};

template <class Rng1, class Rng2>
CombinedCompareResult combinedCompare(const Rng1& rng1, const Rng2& rng2)
{
   using std::begin;

   const auto elementsToCompare = std::min(rng1.size(), rng2.size());

   if (!std::equal(begin(rng1), std::next(begin(rng1), elementsToCompare), begin(rng2)))
      return CombinedCompareResult::NotEqual;
   else if (rng1.size() == rng2.size())
      return CombinedCompareResult::EqualIncludingSize;
   else if (rng1.size() > rng2.size())
      return CombinedCompareResult::EqualAndFirstLarger;
   else
      return CombinedCompareResult::EqualAndSecondLarger;
}

这可以像下面这样使用,并且应该导致与问题中的代码相同的行为。

const auto cmp = combinedCompare(lst, a);

if (cmp == CombinedCompareResult::EqualIncludingSize)
    std::cout << "Same a = a1" << std::endl;
else if (cmp == CombinedCompareResult::EqualAndFirstLarger)
    std::cout << "Same a gt a1" << std::endl;
else if (cmp == CombinedCompareResult::EqualAndSecondLarger)
    std::cout << "Same a1 gt a" << std::endl;

【讨论】:

    猜你喜欢
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多