3

以下の$test配列を「日付」と「サイト」で並べ替えました。

$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はオプションです(つまり、必須ではありません)。

私はこの同様の投稿(および他の投稿)を見つけましたが、実装方法がわかりません。 価値に基づいて関連するすべてのものを取得する

私は頭を回転させるさまざまな方法を試しましたが、どんな助けでも大歓迎です!

4

3 に答える 3

2

You can simply use 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);

Output

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

于 2012-11-03T23:41:36.860 に答える
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"
  }
}
于 2012-11-03T23:31:08.627 に答える
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を保持するという追加の利点がありますが、特に最適化されていない可能性があります。

于 2012-11-03T23:33:03.903 に答える