Comparar dos arreglos

9 views
Skip to first unread message

SeMiAlCruz

unread,
May 19, 2015, 8:20:57 PM5/19/15
to ph...@googlegroups.com
Buen día jóvenes,

Estoy intentando comparar dos arreglos para decidir si hago un insert, un update o un delete.

El primer arreglo contiene los datos "frescos", el otro es producto de una consulta a la tabla donde tengo que almacenar.

Por el momento lo estoy intentando así:

$update = array_intersect($post, $database);
$insert = array_diff($post, $database);
$delete = array_diff($database, $post);

Valido, por ejemplo, si $update no esta vacío, actualizo.

Hasta aquí todo bien, mis problemas empiezan cuando todo esto lo tengo que hacer dentro de un ciclo porque todo el detalle viene en el post. Entonces uso el arreglo 1 (post) como base para el ciclo, es decir:

foreach($post as $data)
{
if(!empty($update)){
Hacer el insert
}
}

Esto falla cuando en la misma secuencia tengo que ejecutar las tres tareas, ya que en ese caso el count del arreglo no coincide con el número de veces que tengo que hacer cada cosa.

Para usar un ejemplo mas concreto:

Post = A,B,C,D
Data = B,C,E

Recorre el ciclo 4 veces, pero tengo que actualizar 2 veces, insertar 2 veces y borrar 1 vez.

Espero que mi explicación no este muy confusa y sobre todo que alguien me de un poco de luz. No está de más decir que estoy un poco desesperado ya.

Gracias.

Stuardo -StR- Rodríguez

unread,
May 20, 2015, 9:01:50 AM5/20/15
to ph...@googlegroups.com

2015-05-19 20:20 GMT-04:00 SeMiAlCruz <semia...@gmail.com>:

Esto falla cuando en la misma secuencia tengo que ejecutar las tres tareas, ya que en ese caso el count del arreglo no coincide con el número de veces que tengo que hacer cada cosa.

A ver, me perdi.  Usando tu ejemplo sería algo así:

$original = ['A', 'B', 'C'     ];

$nuevo    = [     'B', 'C', 'D'];


$update = array_intersect($original, $nuevo); // [B, C]
$insert = array_diff($$nuevo, $original);     // [D]
$delete = array_diff($original, $nuevo);      // [A]

Todo parece bien. ¿Cuál secuencia? ¿Cual count de cual arreglo?

--
Stuardo -StR- Rodríguez| Mercenary Web Developer| La Maphpia
http://maphpia.com| email:  s...@maphpia.com| g-hangouts: s...@maphpia.com
office: +502 2221-9830| mobile: +502 4210-8819| skype: stuardo_str

SeMiAlCruz

unread,
May 20, 2015, 12:43:12 PM5/20/15
to ph...@googlegroups.com
Lo ilustraste muchísimo mejor que yo.

Luego de eso hago un foreach($original){} eso quiere decir que recorre 3 veces el ciclo

Dentro del ciclo valido, para cada arreglo, si están vacíos if(!empty($update)); si no lo están ejecuto, en este caso, el update a la db. Lo mismo para el insert y el delete.

Ahora bien, y aquí viene los del "count" que no quedó claro, si te das cuenta en el ejemplo, tendría que hacer dos update, un delete y un insert (4 tareas), pero mi ciclo lo recorro solo 3 veces ¿Como hago con la tarea restante?

P.D. Puede ser que mi planteamiento desde el principio esté todo mal, es por eso que vengo a buscar luz.

Stuardo -StR- Rodríguez

unread,
May 20, 2015, 12:49:59 PM5/20/15
to ph...@googlegroups.com
2015-05-20 12:43 GMT-04:00 SeMiAlCruz <semia...@gmail.com>:
Ahora bien, y aquí viene los del "count" que no quedó claro, si te das cuenta en el ejemplo, tendría que hacer dos update, un delete y un insert (4 tareas), pero mi ciclo lo recorro solo 3 veces ¿Como hago con la tarea restante?

¿Cómo los estás recorriendo? No entiendo porqué los estarías recorriendo solo 3 veces. Yo lo haría así:

$original = ['A', 'B', 'C'     ];
$nuevo    = [     'B', 'C', 'D'];

$update = array_intersect($original, $nuevo); // [B, C]
$insert = array_diff($$nuevo, $original);     // [D]
$delete = array_diff($original, $nuevo);      // [A]

foreach ($update as $element) {
    $db->update($element);
}
foreach ($insert as $element) {
    $db->insert($element);
}
foreach ($delete as $element) {
    $db->delete($element);
}

Ahí no hay pierde. El foreach recorre los arreglos las veces que sea necesario.

Alejandro Velasquez

unread,
May 20, 2015, 12:57:08 PM5/20/15
to ph...@googlegroups.com
saludos , si entendi bien ,.... para responder a tu duda es que

1. estas recorriendo 3 veces el arreglo original 
2. pero no recorres el arreglo Nuevo  por eso te falta el 2do insert.

 Una solucion es lo que hace Stuardo al recorrer ambos arreglos por instruccion .




--
--
PHPGT :: Grupo de PHPeros de Guatemala
email: ph...@googlegroups.com
reglas de uso: https://sites.google.com/site/grupophpgt

---
Has recibido este mensaje porque estás suscrito al grupo "PHPGT Grupo de PHPeros de Guatemala" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a phpgt+un...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

SeMiAlCruz

unread,
May 20, 2015, 1:08:03 PM5/20/15
to ph...@googlegroups.com
Entiendo perfectamente tu punto, y creo que sería la solución perfecta si el arreglo $original fuera solo de una dimensión. En realidad viene mas o menos así:

$post = [0] => ['producto', 'precio', 'descripción'], [1] => ['producto', 'precio', 'descripción'], [2] => ['producto', 'precio', 'descripción'];

Y yo hago esto, para que array_diff() y array_intersect() me funcionen bien:

foreach ($post as $otro){
$original[] = $otro['producto'];
}

foreach ($db as $otro){
$nuevo[] = $otro['producto']
}

$update = array_intersect($original, $nuevo);

Con todo esto quiero dar a entender que $update no tiene toda la información que quiero actualizar, solo está 'producto' y necesito también 'precio' y 'descripcion'.

La única solución que se me ocurre en el caso que me planteas sería volver a hacer una consulta dentro de cada foreach para obtener el resto de información, y creo que eso afectaría el rendimiento.

Douglas

unread,
May 20, 2015, 1:20:38 PM5/20/15
to ph...@googlegroups.com
Una pregunta, cual es la finalidad de lo que quieres hacer? Por lo que veo esto puede ser algo que le puedas delegar a la base de datos.


--
Enviado desde mi Gmail

--

SeMiAlCruz

unread,
May 20, 2015, 1:24:30 PM5/20/15
to ph...@googlegroups.com
En resumen es un grid que tengo del lado del cliente (navegador) en el que capturo información y necesito guardar en la base de datos.

Si se puede hacer directamente en la DB sería excelente, solo que no tengo idea de cómo.

Douglas

unread,
May 20, 2015, 1:38:28 PM5/20/15
to ph...@googlegroups.com
Otra duda. Ese grid, tiene toda la tabla? Si ese fuera el caso, creo que lo mas eficiente seria hacer un truncate de la tabla e insertar todos los datos. Usando este método se podría realizar con 2 queries.

TRUNCATE tabla; 
-- Si la db no lo soporta usa DELETE FROM tabla
INSERT INTO tabla(a,b,c) values('A1', 'A2', 'A3'),('B1','B2','B3') ...


--
Enviado desde mi Gmail

Stuardo -StR- Rodríguez

unread,
May 24, 2015, 8:15:16 AM5/24/15
to ph...@googlegroups.com

2015-05-20 13:08 GMT-04:00 SeMiAlCruz <semia...@gmail.com>:
$post = [0] => ['producto', 'precio', 'descripción'], [1] => ['producto', 'precio', 'descripción'], [2] => ['producto', 'precio', 'descripción'];

_YO_ metería el ID para facilitar todo. Si viene el ID, sabés que tenés que hacer update, si viene el ID nulo, sabés que es nuevo. Si no viene, es para borrar

$_POST['productos'] = [
    0 => ['id' => 1234, 'producto' => 'lapiceros', ''descripcion' => 'lapirceros bic', 'precio' => 2.00],
    1 => ['id' => 1234, 'producto' => 'lápices, ''descripcion' => 'lapiz mongol', 'precio' => 1.50],
    2 => ['id' => null, 'producto' => 'borradores', ''descripcion' => 'nuevo, 'precio' => 2.00],
];

$noBorrar = [];
foreach ($_POST['productos'] as $producto) {
    if ($producto['id'] {
        $db->update($producto['id'], $producto);  // supongamos que update recibe ID, datos
    } else {
        $producto['id] = $db->insert($producto); // suponemos que insert retorna ID insertado
    }
    $noBorrar[] = $producto['id];
}
$noBorrar = implode(', ', $noBorrar);
$db->query("DELETE FROM productos WHERE id NOT IN ($noBorrar)");

¿Te funcionaría algo así?
Reply all
Reply to author
Forward
0 new messages