在PHP中压缩关联数组

36

假设我有一个数组:

$array = Array(
  'foo' => 5,
  'bar' => 12,
  'baz' => 8
);

我想在视图中打印一行文本,如下所示:

"这些值是:foo(5),bar(12),baz(8)"

我可以这样做:

$list = Array();
foreach ($array as $key => $value) {
  $list[] = "$key ($value)";
}
echo 'The values are: '.implode(', ',$list);

但是我觉得应该有更简单的方法,而不必创建额外的$list数组。我已经尝试了array_maparray_walk,但都没有成功。

所以我的问题是:最好的、最短的方法是什么?


我不知道有没有内置函数可以做到这一点。只有 var_export 和 var_dump,但它们显示的格式与您想要的不同。 - casraf
我建议您也看看http_build_query函数。它的输出格式不是您所要求的,但是非常容易实现。 - T30
10个回答

38

对我来说,最好、最简单的解决方案是这样的:

$string = http_build_query($array, '', ',');

http_build_query (php.net)


3
这对我来说是最好的解决方案。简单而且不需要重新发明轮子。 - Simon Savai
1
这很酷,但是由于编码的原因,你可能得不到想要的结果。但对于简单情况来说效果还不错。 - Sauleil
使用该方法,您无法更改所请求的等于运算符。 - pascalvgemert
请注意,此函数对源数组中的键和值进行URL编码。 - ns16
2
这应该是 $string = urldecode ( http_build_query($array, '', ',') ) ; 以获取非 ASCII 字符串。 - Salem
在我的情况下,大多数数组值都会丢失。构建的查询已将它们过滤掉了。 - Brad

32

array_map存在的问题在于回调函数不接受键名作为参数。你可以编写自己的函数来填补这个空白:

function array_map_assoc( $callback , $array ){
  $r = array();
  foreach ($array as $key=>$value)
    $r[$key] = $callback($key,$value);
  return $r;
}

现在你可以这样做:

echo implode(',',array_map_assoc(function($k,$v){return "$k ($v)";},$array));

2
太棒了!我也给所有的答案点了赞,但我选择这个 :) 可以轻松地在一行代码中添加,并且非常灵活。 - Alec
2
会不会产生额外的数组遍历(一个用于 array_map_assoc,另一个用于 implode)? - CDuv

10

有一种方法,但是它相当冗长(可能不太高效):

<?php
$array = Array(
  'foo' => 5,
  'bar' => 12,
  'baz' => 8
);

// pre-5.3:
echo 'The values are: '. implode(', ', array_map(
   create_function('$k,$v', 'return "$k ($v)";'),
   array_keys($array),
   array_values($array)
));

echo "\n";

// 5.3:
echo 'The values are: '. implode(', ', array_map(
   function ($k, $v) { return "$k ($v)"; },
   array_keys($array),
   array_values($array)
));
?>

你的原始代码在我看来很好。


你可以在php5.3中用function ($k, $v) { return "$k ($v)"; }替换create_function()(它不比eval()更好,因为它使用了eval() ;) 只是一点小建议)。 - KingCrunch
@KingCrunch:确实,在5.3中使用实际的lambda更好。然而,我仍然写create_function()(这很好,因为这里没有用户提供的代码...让我们忽略完全无关的eval()-bashing),直到5.3在生产平台上广泛使用。 - Lightness Races in Orbit
@KingCrunch:(我编辑了我的问题,避开了变量插值的问题。) - Lightness Races in Orbit
我通常会同时提供5.3闭包和早期的create_function()解决方案。我不想再次开始关于旧的eval()讨论,我只是认为值得注意。然而,使用5.3闭包,我认为它并不是“太”啰嗦。我喜欢那些array_map()(等等)的东西 :) - KingCrunch
@KingCrunch: 可能吧 :) 我会编辑进去的。但是,使用 array_map 时,你仍然需要将键和值作为单独的数组提供.. 这很糟糕。 - Lightness Races in Orbit

8
你可以在迭代时将值打印出来:
echo 'The values are: ';
foreach ($array as $key => $value) {
  $result .= "$key ($value),";
}
echo rtrim($result,',');

@yi_H,没错;那正是我想要避免的。 - Alec
将 echos 转换为变量,并在 foreach 之后使用以下代码:echo trim($variable, ','); - Glass Robot
循环外:$comma = ''; 循环开始时内部 echo $comma; 循环结束时内部 $comma = ','; - Salman A
感觉使用 trim()$comma = ''; 越来越像是hack了。对我来说感觉不够简洁。 - KingCrunch
这只是OP原始方法的不太整洁的版本。 - Lightness Races in Orbit

3

参考@linepogl的答案,我编辑了代码,使其更加简单,并且它可以正常工作。

function array_map_assoc($array){
  $r = array();
  foreach ($array as $key=>$value)
    $r[$key] = "$key ($value)";
  return $r;
}

然后,只需使用以下方式调用该函数

echo implode(' , ', array_map_assoc($array));

2

显然,Roberto Santana 提出的解决方案是最有用的。只需要一个约定,如果您想用它来解析html属性(例如data),您需要使用双引号。 这是一种方法:

Example: var_dump( '<td data-'.urldecode( http_build_query( ['value1'=>'"1"','value2'=>'2' ], '', ' data-' ) ).'></td>');

Output: string '<td data-value1="1" data-value2=2></td>' (length=39)

0

我想出了

    foreach ($array as &$item)
    {
        $item = reset($item);
    }
    $array = implode(', ', $array);
    var_dump($array);

0
我是这样做的:
  • 首先,我定义一个新数组来填充我的现有数组的值
  • 我检查我的关联数组是否设置并且不为空
  • 然后循环我的数组,并用值填充新数组
  • 循环结束后,我将新数组合并为字符串

正如你所看到的:

$new_array = [];

if (isset($array) && $array != null) {
    foreach ($array as $el) {$new_array[] = $el->value;}
    $new_array = implode(',', $new_array);
}

echo $new_array;

0
循环遍历数组并在循环结束前放置,
$index = 0; // index
$len = count($array); // Length of the array

// Loop throw the array
foreach($array as $key => $a) {
   echo "$key ($a)" . ($index != $len - 1 ? ',' : '');
   $index++;
}

0

echo json_encode($array); 如果它不是一个有效的数组,它将返回 null。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接