按一列对数组行进行分组,如果有多个值,则仅从另一列创建子数组


Group array rows by one column and only create a subarray from another column if more than one value

如何

对二维数组中的行数据进行分组,并且仅在相应组包含多个值时才创建另一列的子数组?

换句话说,我需要按id对行进行分组,并有条件地重组数组数组,使其具有 2 或 3 级的可变深度。

输入:

[
    ['id' => 567, 'value' => 780],
    ['id' => 676, 'value' => 743],
    ['id' => 676, 'value' => 721],
    ['id' => 234, 'value' => 766],
    ['id' => 234, 'value' => 680]
]

期望输出:

[
    ['id' => 567, 'value' => 780],
    ['id' => 676, 'value' => [743, 721]],
    ['id' => 234, 'value' => [766, 680]]
]

您确定要在一个值时将值作为整数,在有更多值时将值作为数组吗?

<?php
$array = array(
    array('id' => 567, 'value' => 780),
    array('id' => 676, 'value' => 743),
    array('id' => 676, 'value' => 721),
    array('id' => 234, 'value' => 766),
    array('id' => 234, 'value' => 680)
);
foreach ($array as $item) {
    $result[$item['id']][] = $item['value'];
}
foreach ($result as $id => $value) {
    if (count($value) > 1) {
        $output[] = array(
            'id' => $id,
            'value' => $value
        );
    } else {
        $output[] = array(
            'id' => $id,
            'value' => $value[0]
        );
    }
}
echo '<pre>';
print_r($output);
echo '</pre>';
?>

如果不是

<?php
$array = array(
    array('id' => 567, 'value' => 780),
    array('id' => 676, 'value' => 743),
    array('id' => 676, 'value' => 721),
    array('id' => 234, 'value' => 766),
    array('id' => 234, 'value' => 680)
);
foreach ($array as $item) {
    $result[$item['id']][] = $item['value'];
}
foreach ($result as $id => $value) {
    $output[] = array(
        'id' => $id,
        'value' => $value
    );
}
echo '<pre>';
print_r($output);
echo '</pre>';
?>

试试这个

$array['key1'] = array(
    0=>array('id'=>567, 'value'=>780),
    1=>array('id'=>676, 'value'=>743),
    2=>array('id'=>676, 'value'=>721),
    3=>array('id'=>234, 'value'=>766),
    4=>array('id'=>234, 'value'=>780)
    );
foreach($array['key1'] as $subarray){
    $group_id = $subarray['id'];
    if(!isset($return[$group_id]))
        $return[$group_id] = $subarray;
    else{
        if(is_array($return[$group_id]['value']))
            array_push($return[$group_id]['value'], $subarray['value']);
        else 
            $return[$group_id]['value'] = array($subarray['value'], $return[$group_id]['value']);
    }
}
// reset grouping keys into 0,1...
$return = array_values($return);
print_r($return);

在那里,所有的工作都为您完成。这是多么容易啊!

//create the array as you have now
$array[0] = ['id'=>567, 'value'=>780];
$array[1] = ['id'=>676, 'value'=>743];
$array[2] = ['id'=>676, 'value'=>721];
$array[3] = ['id'=>234, 'value'=>766];
$array[4] = ['id'=>234, 'value'=>780];
print_r($array);
print chr(10).chr(10);
//create a new array with the values combined on key
$concat = array();
foreach($array as $val) {
  $i = $val['id'];
  $v = $val['value'];
  if (!is_array($concat[$i]))
    $concat[$i] = array();
  $concat[$i][] = $v;
}
print_r($concat);
print chr(10).chr(10);
//create a new array to show the data as you want.
$newarray = array();
foreach($concat as $key=>$val) {
  $t = array();
  $t['id'] = $key;
  if (count($val)==1)
    $t['value'] = $val[0];
  else {
    $t['value'] = array();
    foreach($val as $v)
      $t['value'][] = $v;
  } 
  $newarray[] = $t;
}
print_r($newarray);
print chr(10).chr(10);

结果:

Array
(
    [0] => Array
        (
            [id] => 567
            [value] => 780
        )
    [1] => Array
        (
            [id] => 676
            [value] => 743
        )
    [2] => Array
        (
            [id] => 676
            [value] => 721
        )
    [3] => Array
        (
            [id] => 234
            [value] => 766
        )
    [4] => Array
        (
            [id] => 234
            [value] => 780
        )
)

Array
(
    [567] => Array
        (
            [0] => 780
        )
    [676] => Array
        (
            [0] => 743
            [1] => 721
        )
    [234] => Array
        (
            [0] => 766
            [1] => 780
        )
)

Array
(
    [0] => Array
        (
            [id] => 567
            [value] => 780
        )
    [1] => Array
        (
            [id] => 676
            [value] => Array
                (
                    [0] => 743
                    [1] => 721
                )
        )
    [2] => Array
        (
            [id] => 234
            [value] => Array
                (
                    [0] => 766
                    [1] => 780
                )
        )
)
<?php
$arr['key1']    = array(
    array(
        'id'    => 567, 
        'value' => 780, 
    ), 
    array(
        'id'    => 676, 
        'value' => 743, 
    ), 
    array(
        'id'    => 676, 
        'value' => 721, 
    ), 
    array(
        'id'    => 234, 
        'value' => 766, 
    ), 
    array(
        'id'    => 234, 
        'value' => 780, 
    ), 
);
/* handle element merge */
function array_internal_merge_func($a, $b) {
    if ( is_array($a['value']) )
        $a['value'][]   = $b['value'];
    else 
        $a['value']     = array($a['value'], $b['value']);
    return $a;
}
/* handle array merge */
function array_internal_merge($array, $key, $merge_func) {
    $hashed = array();
    $result = array();
    foreach ( $array as $idx => $ele ) 
        $hashed[$ele[$key]][]   = $idx;
    foreach ( $hashed as $key => $idxies ) {
        reset($idxies);
        $idx0           = current($idxies);
        $result[$idx0]  = $array[$idx0];
        while ( $idx = next($idxies) ) 
            $result[$idx0]  = $merge_func($result[$idx0], $array[$idx]);
    }
    return $result;
}
print_r(array_internal_merge($arr['key1'], 'id', 'array_internal_merge_func'));

这个任务当然可以通过一个循环简洁地完成。

使用id列值作为临时第一级键。 这使得识别重复项变得最有效和最容易。

迭代时:

  1. 如果一行的id对结果数组来说是新的,则将整行(以其原始的平面结构)推入结果数组;或

  2. 如果之前遇到过行的id,则在将当前行的value推送到该子数组之前,将存储的行的 value 元素强制转换为数组。

如果不希望结果具有id值作为第一级键,请调用 array_values() 以重新索引结果。

下面实现的特殊操作是,当将标量或 null 数据类型强制转换为数组时,该值将成为新形成的数组的唯一元素。 如果数组显式转换为数组,则对数据结构根本没有影响。 这就是为什么(array)可以无条件地应用于else分支的原因。

代码:(演示)

foreach ($array as $row) {
    if (!isset($result[$row['id']])) {
        $result[$row['id']] = $row;
    } else {
        $result[$row['id']]['value'] = array_merge(
            (array) $result[$row['id']]['value'],
            [$row['value']]
        );
    }
}
var_export(array_values($result));
<小时 />

没有array_merge()的替代方案:(演示)

foreach ($array as $row) {
    if (!isset($result[$row['id']])) {
        $result[$row['id']] = $row;
    } else {
        $result[$row['id']]['value'] = (array) $result[$row['id']]['value'];
        $result[$row['id']]['value'][] = $row['value'];
    }
}
var_export(array_values($result));
<小时 />

array_reduce()的替代方案:(演示)

var_export(
    array_values(
        array_reduce(
            $array,
            function($result, $row) {
                if (!isset($result[$row['id']])) {
                    $result[$row['id']] = $row;
                } else {
                    $result[$row['id']]['value'] = (array) $result[$row['id']]['value'];
                    $result[$row['id']]['value'][] = $row['value'];
                }
                return $result;
            }
        )
    )
);