entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

3votos

¿Cuál es la mejor forma de buscar en un array asociativo en PHP?

tengo un array digamos:

$array = array("productoID" => $id, "cantidad" => 15);

y así con varios elementos, después tengo otro arraySearch que buscaría por elemento productoID, el script lo tengo hecho recorriendo con un foreach el $arraySearch y voy buscando por índice, si lo encuentra valida el id y sigo con el control de flujo. La duda surge por motivos de rendimiento, busqué y encontré in_array, pero para arreglos de una dimensión. Gracias

1voto

Leonardo-Tadei comentado

Qué es lo que estás buscando en el array? Podrías poner 2 o 3 ejemplos?
Los $id con numéricos o alfanuméricos?

1voto

miggbriones comentado

ok, te comento mi necesidad (que ya la resolví) sólo quiero ver si hay otra manera más eficiente de realizar dicho procedimiento. Tengo un arreglo con las cantidades que provienen de la base de datos y las guardo en sesion $shopping y otro arreglo con productoID y cantidad que el usuario digíte o cambie a su antojo $array.

Entonces recorro primero $arrayy después por cada item lo busco en la sesion, si existe lo actualizo. Anexo código "completo":

$array = $params["updateQuantities"];
    $shopping = $_SESSION["shoppingCarPartner"];
    $length = count($shopping);

    foreach($array as $element) {
      foreach ($element as $key => $value) {
        if($key == "productID") {
          $productID = $value;
        } else if($key == "quantity") {
          $quantity = intval($value);
        }
      }
      // echo "producto: $product, cantidad: $quantity </br>";
      for ($i=0; $i < $length; $i++) {
       if($shopping[$i]["productID"] == $productoID) {
        $_SESSION["shoppingCartPartner"][$i]["quantity"] = $quantity;
       }
      }
    }

Para darte una idea anexo dump de ambos arreglos:

$array:

array(7) { [0]=> array(2) { ["productID"]=> string(4) "2958" ["quantity"]=> string(1) "1" } [1]=> array(2) { ["productID"]=> string(4) "4948" ["quantity"]=> string(2) "25" } [2]=> array(2) { ["productID"]=> string(4) "2604" ["quantity"]=> string(2) "20" } [3]=> array(2) { ["productID"]=> string(4) "2199" ["quantity"]=> string(1) "5" } [4]=> array(2) { ["productID"]=> string(4) "4140" ["quantity"]=> string(2) "12" } [5]=> array(2) { ["productID"]=> string(4) "5859" ["quantity"]=> string(1) "7" } [6]=> array(2) { ["productID"]=> string(4) "5861" ["quantity"]=> string(2) "28" } }

$shopping:

array(7) { [0]=> array(5) { ["productID"]=> string(4) "2958" ["productCode"]=> string(11) "ROTO-1/2NX2" ["product"]=> string(36) "ROTOMARTILLO 1/2' INDUSTRIAL, 1100 W" ["price"]=> string(7) "1564.66" ["quantity"]=> int(1) } [1]=> array(5) { ["productID"]=> string(4) "4948" ["productCode"]=> string(10) "ROTO-1/2P4" ["product"]=> string(32) "ROTOMARTILLO 1/2', 500 W, PRETUL" ["price"]=> string(6) "402.59" ["quantity"]=> int(25) } [2]=> array(5) { ["productID"]=> string(4) "2604" ["productCode"]=> string(10) "ROTO-1/2A7" ["product"]=> string(37) "ROTOMARTILLO 1/2', PROFESIONAL, 550 W" ["price"]=> string(6) "497.41" ["quantity"]=> int(20) } [3]=> array(5) { ["productID"]=> string(4) "2199" ["productCode"]=> string(10) "ROTO-1/2A8" ["product"]=> string(37) "ROTOMARTILLO 1/2', PROFESIONAL, 650 W" ["price"]=> string(6) "592.24" ["quantity"]=> int(5) } [4]=> array(5) { ["productID"]=> string(4) "4140" ["productCode"]=> string(8) "PARRO-LP" ["product"]=> string(32) "PALA ARROCERA MANGO LARGO T 2000" ["price"]=> string(5) "118.1" ["quantity"]=> int(12) } [5]=> array(5) { ["productID"]=> string(4) "5859" ["productCode"]=> string(5) "AB-12" ["product"]=> string(22) "ABRAZADERA 12, 16-32MM" ["price"]=> string(5) "46.55" ["quantity"]=> int(7) } [6]=> array(5) { ["productID"]=> string(4) "5861" ["productCode"]=> string(5) "AB-20" ["product"]=> string(22) "ABRAZADERA 20, 19-44MM" ["price"]=> string(5) "51.72" ["quantity"]=> int(28) } }

2 Respuestas

3votos

Leonardo-Tadei Puntos227320

Hola @migbriones,

sí, lo que estás haciendo es muy complicado y puede simplificarse un poco.

Primero, la estructura que usás no es un array asociativo, sino una matriz de arrays asociativos, con lo que recorrerla y manejarla es complejo.

Primero, en $params["updateQuantities"], tenés esta matriz que contiene dentro vectores asociativos, 1 vector por cada elemento. podrías simplificar muchísimo esto haciendo que ese elemento sea simplemente un vector asociativo, aprovechando que los ID de los productos no se repiten, digamos que sería:

$params["updateQuantities"] = array("id1" => cantidad1, "id2" => cantidad2, "id3" => cantidad3);

es decir, las claves son los ID y los valores las cantidades.

Con esto te ahorrás el primer bucle interior porque ya no hace falta que "detectes" cuales son las claves y cuales los valores.

Luego, podés hacer algo similar con $_SESSION["shoppingCarPartner"] en el que en vez de un $i arbitrario, podés usar el ID del producto (lo que implica dejar de usar un FOR y pasar a usar un FOREACH para recorrerlo).

De esta manera tu código de actualización quedaría algo como:

    $array = $params["updateQuantities"];
    $shopping = $_SESSION["shoppingCarPartner"];

    foreach($array as $id => $cantidad) {
       if( isset( $shopping[$id]) ) { 
          $_SESSION["shoppingCartPartner"][$id]["quantity"] = $cantidad;
       }
    }

Nótese que si bien el índice de $_SESSION["shoppingCartPartner"] es el ID del producto, el contenido mantiene la misma estructura que tenés actualmente.

Saludos cordiales!

1voto

miggbriones comentado

Excelente. muchas gracias por la correción y ayuda! De nuevo gracias por compartir tu refactorización. Los datos provienen de un script js, ando usando lodash, y creo que puedo hacer lo que me comentas. =)

1voto

magarzon comentado

@migbriones fíjate que la respuesta de @Leonardo-Tadei es prácticamente igual que la mía, así que debe ser la correcta :D

Si usas lodash, puedes hacer lo que decimos sin ningún problema, lodash tiene muchas funciones de manejo de arrays.

1voto

miggbriones comentado

@magarzon si, me ayudé de los dos; @Leonardo-Tadei gracias a los dos. Sí, siempre es bueno preguntar y gente como ustedes que ayudan a los demás. Sigan así compañeros, muy agradecido con ustedes y con la comunidad. Se vé que tienen gran experiencia. Saludos

3votos

magarzon Puntos30650

Después de tu último comentario explicando la situación, así a primera vista se me ocurren dos optimizaciones sobre tu código.

La primera es eliminar el foreach para los parámetros, y acceder por clave, es decir, así:

foreach($array as $element) {
   $productID = isset($element['productID']? $element['productID']: null;
   $quantity = isset($element['quantity']? $element['quantity']: null;

    ...
}

La segunda, si es posible, y ya que el acceso a ese array es por productID, hacer que el array almacenado en sesión ($shopping) sea un array asociativo por producto, es decir, que en lugar de tener

$shopping = [['productID' => '1234', 'quantity' => 1], ['productID' => '5678', 'quantity' => 2], ...];

Sería así:

$shopping = ['1234' => ['productID' => '1234', 'quantity' => 1], '5678' => ['productID' => '5678', 'quantity' => 2], ...];

No creo que te cueste mucho montar el array que guardas en sesión así, y de esta forma, ya puedes hacer esto, mucho más óptimo:

$array = $params['updateQuantities'];
$shopping = $_SESSION['shoppingCarPartner'];

foreach($array as $element) {
   $productID = isset($element['productID']? $element['productID']: null;
   $quantity = isset($element['quantity']? $element['quantity']: null;
   if ($productID && $quantity && isset($shopping[$productID])) {
        $_SESSION['shoppingCartPartner'][$productID]['quantity'] = $quantity;
   }
}

1voto

miggbriones comentado

Excelente, muchas gracias por compartir tu idea de refactorización. Haré las dos y eligiré la menos laboriosa. =)

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta