Как использовать implode для массива объектов stdClass?


У меня есть массив объектов stdClass, и я хочу построить список, разделенный запятыми, используя одно конкретное поле всех этих объектов stdClass. Мой массив выглядит так:

$obj1 = stdClass Object ( [foo] => 4 [bar] => 8 [foo-bar] => 15 );
$obj1 = stdClass Object ( [foo] => 16 [bar] => 23 [foo-bar] => 42 );
$obj1 = stdClass Object ( [foo] => 76 [bar] => 79 [foo-bar] => 83 );

$a = array(1=>$obj1 , 2=>$obj2 , 3=>$obj3);

И я хочу имплод на foo всех stdClass объектов в этом массиве, чтобы создать разделенный запятыми список. Итак, желаемый результат:

4,16,76

Есть ли способ сделать это с помощью implode (или какой-либо другой таинственной функции) без необходимости пропускать этот массив объектов через цикл?

8 13

8 ответов:

Вы могли бы использовать array_map() и implode()...

$a = array_map(function($obj) { return $obj->foo; }, 
               array(1=>$obj1 , 2=>$obj2 , 3=>$obj3));

$a = implode(", ", $a);

На самом деле это лучший способ, который я нашел, кажется, что здесь нет правильного ответа, поскольку массив объектов должен быть в состоянии обрабатывать динамический размер.

$str = implode(',', array_map(function($x) { return $x->foo; }, $a));

Это также кажется самым чистым решением, которое я видел.

Вы действительно можете установить __toString() в классе, предложенном Рэем, но вам не нужно сначала перебирать array. implode() будет непосредственно вызывать функцию __toString() объектов (которая также работает с ассоциативными массивами, кстати).

Очень аккуратным решением для этого является array_reduce() функция, которая сводит массив к одному значению:

$str = array_reduce($a, function($v, $w) {
    if ($v) $v .= ',';
    return $v . $w->foo;
});
echo implode("','",(array)$data->stdArray);

Я думаю, что проще всего было бы создать индексированный массив ID, а затем вызвать implode на array_keys:

$a = array();
$a[4] = stdClass Object ( [foo] => 4 [bar] => 8 [foo-bar] => 15 );
$a[16] = stdClass Object ( [foo] => 16 [bar] => 23 [foo-bar] => 42 );
$a[76] = stdClass Object ( [foo] => 76 [bar] => 79 [foo-bar] => 83 );

echo implode(', ', array_keys($a));

Нет, лучшее, что вы можете сделать, это выполнить итерацию, вызвать tostring() для объекта и поместить результаты в новый массив для вызова implode.

Если это объект 1-го уровня, это сработало для меня.

function implodeObjValues($glue, $obj) { 
    $s = "";
    foreach($obj[1] as $n=>$v) {
        $s .= $glue . $v;
    }
    return substr($s,strlen($glue));
}

function implodeObjLabels($glue, $obj) { 
    $s = "";
    foreach($obj[1] as $n=>$v) {
        $s .= $glue . $n;
    }
    return substr($s,strlen($glue));
}

Может включать многоуровневый процесс по типу, но мне это пока не нужно. Надеюсь, это поможет.

Удобно для преобразования объекта MySQL обратно в массив.

$db = new mysqli("localhost",$usr,$pw,$db);
$row = $db->query("SHOW TABLES");
$a = implodeObjValues("|",$row);