web-dev-qa-db-fra.com

Comparez le plus petit vecteur au plus grand pour vérifier s'il diffère à la fin du plus petit

Nous avons deux vecteurs de taille qui dépendent de l'exécution et nous devons vérifier s'ils sont égaux - les éléments ne diffèrent qu'après la fin du vecteur de taille plus petite. J'ai utilisé std :: equal mais le problème est que je dois d'abord trouver quel vecteur est de taille plus petite, ce qui conduit à une ligne de code supplémentaire:

#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;
    }
  }
}

Le code permettant de comparer deux vecteurs ou de ne différer qu'à la fin d'un vecteur plus petit peut-il être amélioré?

13
Programmer

Vous n'avez besoin que d'un appel de std::equal si vous calculez auparavant la plus petite taille. Je refacturerais le code comme ceci:

#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;
}

Si vous devez conserver la deuxième information sur le vecteur le plus grand, vous pouvez l’atteindre comme ceci, par exemple:

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

Depuis C++ 14, vous pouvez utiliser std::mismatch et vérifier la paire d’itérateurs renvoyée par rapport à la fin de chaque plage:

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

Vous devez également savoir où les éléments commencent à différer et, dans le cas contraire, à quel point le vecteur le plus grand est grand (le début de la sous-gamme que vous ne voulez pas comparer).

23
Nelfeal

Voici une solution C++ 11 pure qui devrait fonctionner pour tout conteneur séquentiel (par exemple, std::vector, std::list, std::deque). Il utilise un type de retour personnalisé, car le type de comparaison que vous affichez dans les extraits de code d'origine contient plus d'informations qu'une simple valeur booléenne ne peut en incorporer.

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;
}

Ceci peut être utilisé comme suit et devrait avoir le même comportement que le code de la question.

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;
0
lubgr