“Error de conversión de matriz a cadena” al llamar a array_diff_assoc() con una matriz multidimensional

7 minutos de lectura

avatar de usuario de user2963765
usuario2963765

Obtengo un error de conversión de matriz a cadena para la siguiente línea:

$diff = array_diff_assoc($stockist, $arr);

Aquí, $arr es una matriz decodificada de un archivo JSON. Utilizando el is_array() función pude verificar que ambos parámetros son matrices. alguien me puede indicar el problema

$stockist = array();
while (!feof($file_handle)) {

    $line_of_text = fgetcsv($file_handle);
    $query = "SELECT * FROM reorderchart WHERE medicine=""
        . trim($line_of_text[3])
        . "" ORDER BY medicine";
    $result = mysql_query($query);

    if (trim($line_of_text[2]) - trim($line_of_text[1]) <= 0) {
        
        while ($row = mysql_fetch_array($result)) {

            $file = "results.json";
            $arr = json_decode(file_get_contents($file),true);
            $pharmacy = trim($row['Medicine']);

            if (isset($stockist[$pharmacy])) {
                    
                $medicine = $stockist[$pharmacy];
                $medicine[] = trim($row['Stockist']);
                $stockist[$pharmacy] = $medicine;

            } else {

                $medicine = array();
                $medicine[] = trim($row['Stockist']);
                $stockist[$pharmacy] = $medicine;
            }
        }
    }
}
$diff = array();
$diff = array_diff_assoc($stockist,$arr);
ksort($diff);
foreach ($diff as $key => $value) {

    echo "<table align='center' border="1">";
    echo "<tr><td align = 'center'> <font color="blue"> $key</td></tr>";
    
    foreach($value as $key1 => $value1) {

        echo "<tr><td align ='center'>$value1</td></tr><br>";
    }
    echo "</table>";
}

  • Posible motivo: arreglos multidimensionales

    – Viacheslav Kondratiuk

    7 de noviembre de 2013 a las 8:02

  • “ambos parámetros son matrices” Claro que lo son, y php no dice nada diferente. El asunto es un conversión de matriz a cadena, no de la otra manera. La pregunta es ¿qué hacen estas matrices? contener.

    – geomagas

    7 de noviembre de 2013 a las 8:03

  • @viakondratiuk Sí, es multidimensional. Pero array_diff() no evalúa solo el primer nivel

    – usuario2963765

    7 de noviembre de 2013 a las 8:09


  • @user2963765 Esta función solo verifica una dimensión de una matriz de n dimensiones. Por supuesto, puede verificar dimensiones más profundas usando array_diff($array1[0], $array2[0]);.

    – Viacheslav Kondratiuk

    7 de noviembre de 2013 a las 8:10


  • Puedes usar un recursive array_diff. mira esto gist.github.com/jondlm/7709e54f84a3f1e1b67bresolvió mi problema…

    – geneowak

    22 de julio de 2020 a las 18:59


Avatar de usuario de Viacheslav Kondratiuk
Viacheslav Kondratiuk

De acuerdo a esto:

php -r 'array_diff(array("a" => array("b" => 4)), array(1));'
PHP Notice:  Array to string conversion in Command line code on line 1
PHP Stack trace:
PHP   1. {main}() Command line code:0
PHP   2. array_diff() Command line code:1

Una de sus matrices es multidimensional.

array_diff solo verifica una dimensión de una matriz n-dimensional. Por supuesto, puede verificar dimensiones más profundas usando array_diff($array1[0], $array2[0]);

  • Me parece como un insecto. El mensaje “Conversión de matriz a cadena” es engañoso en el mejor de los casos.

    – Janis Elmeris

    9 de abril de 2018 a las 11:47

Avatar de usuario de EAT
COMER

Sí, la respuesta estricta es porque “Una de sus matrices es multidimensional”.

Otra nota útil podría ser: dependiendo de sus necesidades de analizar más las diferencias reales – considere primero probar sus arreglos con:

$diff = strcmp(json_encode($stockist), json_encode($arr));

o

$diff = strspn(json_encode($stockist) ^ json_encode($arr), "\0");

o

$diff = xdiff_string_diff(json_encode($stockist), json_encode($arr));

Todas estas opciones compararán todo el árbol de arreglos, no solo el nivel superior.

  • $diff = strcmp(json_encode($stockist), json_encode($arr)); no funcionó, siempre devuelve 0 cuando hay una diferencia entre los dos

    –Robert Sinclair

    12 de agosto de 2019 a las 15:54

avatar de usuario de kenorb
kenorb

Ya que array_diff solo puede tratar con una dimensión, puede:

  • convierta su matriz multidimensional en una dimensión, por ejemplo, mediante:

    • aplanando una matriz multidimensional, por ejemplo:

      while ($arr) {
        list($key, $value) = each($arr); 
        is_array($value) ? $arr = $value : $out[$key] = $value;
        unset($arr[$key]);
      }
      // Now $out is flatten version of $arr.
      
    • serializando la matriz, por ejemplo:

      $results = array_diff(array_map('serialize',$a2), array_map('serialize',$a1)); 
      
  • usar recurso recursivo personalizado array_diff-como función,

  • El aplanamiento de una matriz multidimensional es incorrecto. Cuando se acerca la primera matriz anidada, la función olvida todos los demás valores en $arr original.

    – Kangur

    7 de noviembre de 2017 a las 13:48

  • ¡Perfecto! Unserialize funcionó a diferencia de la respuesta más votada. Solo necesitaba hacer $resultados = array_map(‘unserialize’, $resultados); epílogos para leerlo

    –Robert Sinclair

    12 de agosto de 2019 a las 15:59

  • El segundo ejemplo era exactamente lo que estaba buscando, ¡gracias!

    –Steve Bauman

    12 de septiembre de 2019 a las 0:57

Puedes ver en el documentación de array_diff() que:

Dos elementos se consideran iguales si y solo si (cadena) $elem1 === (cadena) $elem2. En otras palabras: cuando la representación de la cadena es la misma.

Entonces parece que no puede usar esta función con una matriz multidimensional o, de hecho, con cualquier valor que no se pueda convertir en una cadena. Esto se debe a que la función emitirá valores a un string para hacer la comparación.

Puede escribir su propia función para verificar recursivamente las matrices en busca de una diferencia; de hecho, lo siguiente es de los comentarios de los documentos vinculados anteriormente.

Puedes ver el comenta aquí.

function arrayRecursiveDiff($aArray1, $aArray2) { 
    $aReturn = array(); 

    foreach ($aArray1 as $mKey => $mValue) { 
        if (array_key_exists($mKey, $aArray2)) { 
            if (is_array($mValue)) { 
                $aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]); 
                if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; } 
            } else { 
                if ($mValue != $aArray2[$mKey]) { 
                    $aReturn[$mKey] = $mValue; 
                } 
            } 
        } else { 
            $aReturn[$mKey] = $mValue; 
        } 
    } 

    return $aReturn; 
}

De acuerdo con la documentación de PHP para la función.

Nota: dos elementos se consideran iguales si y solo si (cadena) $elem1 === (cadena) $elem2. En palabras: cuando la representación de la cadena es la misma.

Para obtener más información, consulte http://php.net/manual/en/function.array-diff.php

  • Solo necesito comparar llaves. Así que usé array_diff_key(). Pero está devolviendo una matriz nula.

    – usuario2963765

    7 de noviembre de 2013 a las 10:01

  • Si devuelve una matriz vacía, significa que ambas matrices tienen el mismo conjunto de claves.

    – máx.

    7 de noviembre de 2013 a las 15:23

  • Tuve un error en el que tenía dos matrices consideradas diferentes, pero claramente se veían iguales. Esta respuesta me ayudó a comparar su representación de cadenas y, de hecho, era diferente.

    – misterone

    5 de julio a las 19:23


Encontré este mientras trabajaba en una actualización de plataforma para PHP 7.3 desde 5.3 hoy… Dado que estoy almacenando este valor para usarlo más adelante, quería asegurarme de no terminar con una matriz ‘parcialmente’ serializada que puede romper las cosas río abajo.

Gracias Kenorb por llevarme por el camino correcto (voté a favor de tu respuesta). Lo siguiente está funcionando muy bien para mí.

Código:

$a1 = [
  'foo' => 'bar',
  'bar' => [
    'test' => 'test'
  ],
  'foobar' => 'fizzbuzz'
];

$a2 = [
  'foobar' => 'fizzbuzz',
  'herp' => [
    'derp' => 'herpderp'
  ]
];

$diff = array_diff(array_map('serialize', $a1), array_map('serialize', $a2));

$multidimensional_diff = array_map('unserialize', $diff);

print_r($multidimensional_diff);

Producción:

Array
(
    [foo] => bar
    [bar] => Array
        (
            [test] => test
        )

)

  • Solo necesito comparar llaves. Así que usé array_diff_key(). Pero está devolviendo una matriz nula.

    – usuario2963765

    7 de noviembre de 2013 a las 10:01

  • Si devuelve una matriz vacía, significa que ambas matrices tienen el mismo conjunto de claves.

    – máx.

    7 de noviembre de 2013 a las 15:23

  • Tuve un error en el que tenía dos matrices consideradas diferentes, pero claramente se veían iguales. Esta respuesta me ayudó a comparar su representación de cadenas y, de hecho, era diferente.

    – misterone

    5 de julio a las 19:23


Avatar de usuario de TheBlueAssasin
elasesinoazul

Esta es mi solución para un problema similar. Quiero comparar dos matrices asociativas y devolver los valores modificados, pero algunos de los elementos son matrices. Entonces si uso

array_diff_assoc

, me da “Error de matriz a cadena”. Mi función también comparará los elementos que son matrices y, si hay una diferencia, devolverá el elemento de la matriz. Todavía es un trabajo en progreso y no se ha probado exhaustivamente. Por ejemplo:

public static $example1 = [
    'id' => 1,
    'status' => 2,
    'elements' => ['test', 'example'],
    'different' => ['old' => 5, 'new' => 9]
];

public static $example2 = [
    'id' => 1,
    'status' => 3,
    'elements' => ['test', 'example'],
    'different' => ['old' => 5, 'new' => 8]
];

public static function test(){
    die(var_dump(self::udiffAssoc(self::$example1, self::$example2)));
}

public static function udiffAssoc(array $array1, array $array2)
{
    $checkDiff = function ($a, $b) use (&$checkDiff) {
        if (is_array($a) && is_array($b)) {
            return array_udiff_assoc($a, $b, $checkDiff);
        } elseif (is_array($a)) {
            return 1;
        } elseif (is_array($b)) {
            return -1;
        } elseif ($a === $b) {
            return 0;
        } else {
            return $a > $b ? 1 : -1;
        }
    };
    return array_udiff_assoc($array1, $array2, $checkDiff);
}

si ejecuta ::test devolverá:

array(2) {
    ["status"]=>
    int(2)
    ["different"]=>
    array(2) {
    ["old"]=>
    int(5)
    ["new"]=>
    int(9)
  }
}

¿Ha sido útil esta solución?