2011-03-23 23 views
18

Por rango quiero decir un par de iteradores. En seudo C++:¿Existe una forma estándar de comparar dos rangos en C++?

std::vector<int> v1 = { 1, 2, 3, 4, 5 }; 
std::vector<int> v2 = { 2, 3, 4 }; 
if(std::compare_range(v1.begin() + 1, v1.end() - 1, v2.begin(), v2.end()) { 
    std::cout << "Alright\n"; 
} 

compare_range siendo, por supuesto, la función que estoy buscando.

Descargo de responsabilidad: Esta es una función bastante trivial para escribir, lo sé. Pero como todos los programadores, intento ser flojo ;-)

+3

Comparar cómo? Por la igualdad? ¿Equivalencia? ¿Desigualdad? ¿Mayor? ¿Inferior? ¿Más caliente? Colder? ¿Verder? Bluer? ... –

+1

@Tomalak Geret'kal: Olvidaste "mejor". – ereOn

+0

@ereOn: Así que lo hice: o) –

Respuesta

26

std::equal es la plantilla de función que está buscando.

if (std::equal(v1.begin() + 1, v1.end() - 1, v2.begin()) 
{ 
    std::cout << "Alright\n"; 
} 

Tenga en cuenta que std::equal sólo toma tres argumentos, no cuatro.

+0

De alguna manera lo había perdido. Gracias. Ahora que lo he pensado, obviamente no necesito ese cuarto argumento ... :) –

+0

@Pedro: bueno, por razones de "seguridad" sería genial ... –

+2

Este método está bien, cuando el usuario garantiza , que ambos intervalos son de la misma longitud De lo contrario, puede bloquearse o funcionar incorrectamente. –

6

Parece que no hay un método estándar de "una función". Mencionado std :: igual supone, ese segundo rango no es más corto que el primero. Por ejemplo, esto puede provocar daños en la memoria, cuando el segundo intervalo está vacío. Tampoco da respuesta, cuando el segundo rango es más grande.

Combinación de std :: se requiere igual y std :: distancia, o la función de auto-escrita:

template <class InputIterator1, class InputIterator2> 
bool safe_equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) 
{ 
    return (std::distance(first1, last1) == std::distance(first2, last2)) 
    && std::equal(first1, last1, first2); 
} 

función anterior puede atravesar containter dos veces para iteradores de acceso no al azar, sino que utiliza las funciones estándar. Puede ser razonable escribir una implementación propia, si esto no es aceptable.

+0

Correcciones de sintaxis pequeñas: el último argumento debe llamarse 'last2' en lugar de' second2' y primero abrir paréntesis después de que '&&' sea redundante. –

4

Si tiene un medio para determinar que los dos rangos tienen exactamente el mismo número de elementos, std::equal hará. En la práctica, esto no parece ser el caso que a menudo para mí, y la mayoría de los usos que tengo de std::equal son de hecho determinar si una variedad es un prefijo del otro.

Para las comparaciones reales, he encontrado std::lexicographical_compare a ser más útil, aunque la relación que PROMESSES es uno de orden, no de equivalencia. Para la equivalencia, puede aplicarlo dos veces, p.

!lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()) 
&& !lexicographical_compare(b.begin(), b.end(), a.begin(), a.end()) 

pero este más o menos medios de comparación elementos de dos veces (a menos hay una diferencia desde el principio).

Cuestiones relacionadas