组合数组字符串值和丢弃数组元素

时间:2012-11-03 23:23:10

标签: php arrays

我有以下$test数组,按' date '和' site '排序。

$test = array ( 
0 => array ( 
       'id' => '45', 
       'rating' => 'p1', 
       'site' => 'Heavener SW', 
       'time' => '11-03-2012 Sat 10:00:00', 
       ), 
1 => array ( 
       'id' => '45', 
       'rating' => 'h3', 
       'site' => 'Heavener SW', 
       'time' => '11-03-2012 Sat 10:00:00', 
       ),
2 => array ( 
       'id' => '45', 
       'rating' => 'h4', 
       'site' => 'Heavener SW', 
       'time' => '11-03-2012 Sat 16:00:00', 
       ),
3 => array ( 
       'id' => '110', 
       'rating' => 'p3', 
       'site' => 'Red Oak', 
       'time' => '11-03-2012 Sat 16:00:00', 
       ), 
4 => array ( 
       'id' => '110', 
       'rating' => 'h3', 
       'site' => 'Red Oak', 
       'time' => '11-03-2012 Sat 16:00:00', 
       ), 
5 => array ( 
       'id' => '32', 
       'rating' => 'p2', 
       'site' => 'Panopoint', 
       'time' => '11-04-2012 Sun 10:00:00', 
       ) 
 );

我疯狂地尝试将每个“网站” - “时间”组合的“评分”结合起来。

$result = array (
0 => array ( 
       'id' => '45', 
       'rating' => 'p1, h3', 
       'site' => 'Heavener SW',
       'time' => '11-03-2012 Sat 10:00:00', 
       ),
2 => array ( 
       'id' => '45', 
       'rating' => 'h4', 
       'site' => 'Heavener SW', 
       'time' => '11-03-2012 Sat 16:00:00', 
       ),
3 => array ( 
       'id' => '110', 
       'rating' => 'p3, h3', 
       'site' => 'Red Oak', 
       'time' => '11-03-2012 Sat 16:00:00', 
       ),
5 => array ( 
       'id' => '32', 
       'rating' => 'p2', 
       'site' => 'Panopoint', 
       'time' => '11-04-2012 Sun 10:00:00', 
       ) 
 );

网站可以拥有的“评分”数量或者有多少“网站”或“时间”(在合理范围内)没有限制。 保留$result中的索引是可选的(即不必要)。

我发现了这个类似的帖子(和其他人),但我不明白如何实现。 Getting all the related ones based on value

我已经尝试了很多不同的方式,我的头在旋转,非常感谢任何帮助!

3 个答案:

答案 0 :(得分:2)

您只需使用array_reduce

即可
$test = array_reduce($test, function ($a, $b) {
    isset($a[$b['time'] . "|" . $b['id']]) ? $a[$b['time'] . "|" . $b['id']]['rating'] .= "," . $b['rating'] : $a[$b['time'] . "|" . $b['id']] = $b;
    return $a;
});

$test = array_values($test);
var_dump($test);

输出

array
  0 => 
    array
      'id' => string '45' (length=2)
      'rating' => string 'p1,h3' (length=5)
      'site' => string 'Heavener SW' (length=11)
      'time' => string '11-03-2012 Sat 10:00:00' (length=23)
  1 => 
    array
      'id' => string '45' (length=2)
      'rating' => string 'h4' (length=2)
      'site' => string 'Heavener SW' (length=11)
      'time' => string '11-03-2012 Sat 16:00:00' (length=23)
  2 => 
    array
      'id' => string '110' (length=3)
      'rating' => string 'p3,h3' (length=5)
      'site' => string 'Red Oak' (length=7)
      'time' => string '11-03-2012 Sat 16:00:00' (length=23)
  3 => 
    array
      'id' => string '32' (length=2)
      'rating' => string 'p2' (length=2)
      'site' => string 'Panopoint' (length=9)
      'time' => string '11-04-2012 Sun 10:00:00' (length=23)

See Live Demo

答案 1 :(得分:1)

由于保留密钥是可选的,因此一个简单的选择是在循环原始密钥时构建一个由唯一对site|time键控的新数组。

对于其中的每一个,我们还将创建一个rating值数组,最后,implode()将该数组转换为字符串,返回'ratings'键。

$rekeyed = array();
foreach ($test as $item) {
  // Build temporary key by concatenating site, time
  $key = $item['site'] . '|' . $item['time'];
  // If it already exists, add to the ratings
  if (isset($rekeyed[$key])) {
    $rekeyed[$key]['ratings'][] = $item['rating'];
  }
  else {
    // Otherwise, set the key and the ratings array
    $rekeyed[$key] = $item;
    // And set the first rating, initialized as an array
    $rekeyed[$key]['ratings'] = array();
    $rekeyed[$key]['ratings'][] = $item['rating'];
  }
}

// Finally, loop over and implode all the ratings back into a comma-separated string
foreach ($rekeyed as &$item) {
  $item['rating'] = implode(',', $item['ratings']);
  // Don't need the 'ratings' array anymore, unset it
  unset($item['ratings']);
}

var_dump($rekeyed);

输出:

array(4) {
  ["Heavener SW|11-03-2012 Sat 10:00:00"]=>
  array(5) {
    ["id"]=>
    string(2) "45"
    ["rating"]=>
    string(5) "p1,h3"
    ["site"]=>
    string(11) "Heavener SW"
    ["time"]=>
    string(23) "11-03-2012 Sat 10:00:00"
  }
  ["Heavener SW|11-03-2012 Sat 16:00:00"]=>
  array(5) {
    ["id"]=>
    string(2) "45"
    ["rating"]=>
    string(2) "h4"
    ["site"]=>
    string(11) "Heavener SW"
    ["time"]=>
    string(23) "11-03-2012 Sat 16:00:00"
  }
  ["Red Oak|11-03-2012 Sat 16:00:00"]=>
  array(5) {
    ["id"]=>
    string(3) "110"
    ["rating"]=>
    string(5) "p3,h3"
    ["site"]=>
    string(7) "Red Oak"
    ["time"]=>
    string(23) "11-03-2012 Sat 16:00:00"
  }
  ["Panopoint|11-04-2012 Sun 10:00:00"]=>
  &array(5) {
    ["id"]=>
    string(2) "32"
    ["rating"]=>
    string(2) "p2"
    ["site"]=>
    string(9) "Panopoint"
    ["time"]=>
    string(23) "11-04-2012 Sun 10:00:00"
  }
}

答案 2 :(得分:0)

我认为PHP foreach循环按顺序排列,所以这应该有效。我没有测试过,所以让我知道它是怎么回事。

$previous_id = '';
// for each row, check if it was the same as the previous row (since you have sorted it properly)
foreach($result as $k => $row){
    // if it matches the previous, add the rating and remove now duplicate row
    if ($row['time'] == $result[$previous_id]['time']
     && $row['site'] == $result[$previous_id]['site']){
        $result[$previous_id]['rating'] .= ', '.$row['rating'];
        unset($result[$k]);
    } // otherwise, set new previous_id to check
    else {
        $previous_id = $k;
    }
}

这样可以保留您遇到的第一个行ID,但可能无法进行特别优化。