Ordenar matriz de CGPoints

Estoy tratando de averiguar cuál sería la forma más rápida/limpia de ordenar una matriz de CGPoints. Creo que podría lograr esto usando bucles, pero puede que no sea lo más rápido y espero que no sea la forma más limpia. Me gustaría tomar una matriz de CGPoints aleatorios y ordenarlos, por ejemplo, por la coordenada x más pequeña a la x más grande o más pequeña y coordenada y mayor.

preguntado el 22 de mayo de 12 a las 20:05

¿Es posible agregarlos a una estructura ordenada? Creo que puedes usar un NSMutableArray y llamar al método: - (void)insertObject:(id)anObject atIndex:(NSUInteger)index -

No tengo ningún problema en agregarlos (a través de NSValue) a un NSArray o NSMutableArray, etc. Me gustaría saber cómo clasificarlos u ordenarlos según ciertos criterios. -

3 Respuestas

Después del comentario correcto de Chuck, actualicé la respuesta usando el método sortUsingComparator:

Aquí está el código completo con datos de muestra:

Primero generamos 100 valores aleatorios que ingresamos al Array:

NSMutableArray *testArray = [[NSMutableArray alloc] initWithCapacity:100];
for (int i=0; i<100; i++) {
    CGPoint testPoint = CGPointMake(arc4random()%100, arc4random()%100);
    [testArray addObject:[NSValue valueWithCGPoint:testPoint]];
}

y aquí está el código real para ordenar la matriz:

[testArray sortUsingComparator:^(id firstObject, id secondObject) {
    CGPoint firstPoint = [firstObject CGPointValue];
    CGPoint secondPoint = [secondObject CGPointValue];
    return firstPoint.x>secondPoint.x;
}];

finalmente podemos verificar que la matriz fue ordenada imprimiéndola:

NSLog(@"%@",testArray);

contestado el 22 de mayo de 12 a las 21:05

NSSortDescriptor no puede hacer nada con estructuras AFAIK. - Arrojar

Tienes razón Chuck, he editado la respuesta para usar el método sortUsingComparator - lefteris

Justo lo que necesitaba. Pero, ¿puedes explicar cómo funciona esa comparación? ¿Qué está haciendo exactamente cuando devuelve "firstPoint.x> secondPoint.x"? - DaveMac

Toma los objetos de la matriz por 2 y los compara entre ellos. Si el primer objeto es mayor que el segundo, mueve el primer objeto después del segundo, logrando un ordenamiento ascendente. Si desea una clasificación descendente, debe comparar lo opuesto, también conocido como return firstPoint.x segundoPunto.x) devuelve NSOrdenadoAscendente; si no (primerPunto.x lefteris

El C qsort() La función es probablemente su mejor apuesta si solo tiene una matriz simple de CGPoints. Algo como esto:

int compareXCoords(CGPoint *a, CGPoint *b) {
    return b->x - a->x;
}

// Later:

CGPoint points[100];
// initialize points somehow
qsort(points, 100, sizeof(CGPoint), compareXCoords);
// points is now sorted by the points' x coordinates

contestado el 22 de mayo de 12 a las 20:05

Un par de cosas... ¿cómo funciona exactamente esa fórmula (b->x - a->x)? Además, mis arreglos son todos Objective-C y preferiría trabajar con objetos, solo porque no tengo mucha experiencia en c procedimental. ¿Tengo que asignar y liberar las matrices c? - DaveMac

@daveMac: Se supone que la devolución de llamada de qsort devuelve un int que indica cómo se deben ordenar los valores: cualquier número positivo significa que están ascendiendo, cualquier número negativo significa que están descendiendo y 0 significa igual. Restar el primer número del segundo hace precisamente eso. En cuanto a cómo se almacenan los puntos: ya te lo pensé tenido una matriz C. CGPoint es una estructura C, así que cuando dijiste que tenías una matriz de ellos, asumí que te referías a una matriz C ya que no hay una colección Cocoa que realmente pueda almacenar un CGPoint. Si tiene un NSMutableArray de NSValues, entonces la respuesta de Lefteris es equivalente. - Arrojar

Gracias Chuck, agradezco la explicación. ...tanto que aprender todo el tiempo. - DaveMac

Según mi comentario, es una buena solución insertarlos en un NSMutableArray manteniendo el orden que decidas.

Tienes que hacer algo como esto:

NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:1];

CGPoint candidate;
// Look for the position it has to be
int 0;
for (CGPoint point in array) {
    i++;
    // Compare candidate with current point
    // You have to define this condition, when point is greater than candidate
    if (point > candidate) {
        break;
    }
}
[array insertObjectAtIndex:i-1];

Tal vez mi código tenga algunos errores, no puedo verificar si es correcto ahora.

contestado el 22 de mayo de 12 a las 20:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.