人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHPで以下の配列があり
配列A
Array
(
[0] => Array
(
[TEST1] => 2222
[TEST2] => OK
[TEST3] => 8888
)
[1] => Array
(
[TEST1] => 33333
[TEST2] => NG
[TEST3] => 9999
)
[2] => Array
(
[TEST1] => 44444
[TEST2] => OK
[TEST3] => 77777
)
)
をまずTEST3の項目で昇順にソートして
TEST2の項目がOK、NG、OK、NGみたいに
なるようにするにはどうしたらいいですか?
もしもOK、OK、OKなどに並ぶようなら
最初にOKが格納されたら、次にNGが来るまでの
配列の値は削除するようにしたいのですが
どうしたらいいのでしょうか?
結果:
Array
(
[0] => Array
(
[TEST1] => 4444
[TEST2] => OK
[TEST3] => 7777
)
[1] => Array
(
[TEST1] => 33333
[TEST2] => NG
[TEST3] => 9999
)
)

●質問者: hopefully
●カテゴリ:就職・転職 ウェブ制作
✍キーワード:8888 NG PHP test ソート
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● t_shiono
●27ポイント

地道にやってもいいと思いますが、スマートに書くとしたら、これでどうでしょう?

function cmp($lhs, $rhs) {
 $lv = $lhs["TEST3"];
 $rv = $rhs["TEST3"];
 if ($lv < $rv) {
 return -1;
 } else if ($lv > $rv) {
 return 1;
 } else {
 return 0;
 }
}

$expect = 0;
function check($item) {
 global $expect;

 $list = array("OK", "NG");
 if (strcmp($item["TEST2"], $list[$expect]) == 0) {
 $expect = ($expect + 1) % 2;
 return true;
 } else {
 return false;
 }
}



$a = array(
 array("TEST1" => 2222, "TEST2" => "OK", "TEST3" => 8888),
 array("TEST1" => 3333, "TEST2" => "NG", "TEST3" => 9999),
 array("TEST1" => 4444, "TEST2" => "OK", "TEST3" => 7777));

usort($a, "cmp");
$result = array_filter($a, "check");

◎質問者からの返答

ありがとうございます。


2 ● tezcello
●27ポイント

こんなのでどうでしょうか?

TEST3, TEST1, TEST2 の順になる様に各項目を連結し、配列を作ります。

これをソートすると、TEST3 の項目でソートした事になります。

この配列の全要素において、最後の3文字が '_OK' であるかをチェックします。(2文字だけでも可)

既に '_OK' の直後であれば、次の値を調べます。

そうでない場合は結果配列に格納します。

連結した時に、各項目の間に挟んだ文字 '_' で分割し、

それぞれを項目名をキーとした連想配列として格納する。

$array_A = array(
 array('TEST1'=>'2222', 'TEST2'=>'OK', 'TEST3'=>'8888')
 ,array('TEST1'=>'33333', 'TEST2'=>'NG', 'TEST3'=>'9999')
 ,array('TEST1'=>'44444', 'TEST2'=>'OK', 'TEST3'=>'7777') // 質問文での元配列は '77777' ですが、結果の配列に合わせました
 );

foreach($array_A as $a){
 $array_B[] = $a['TEST3'].'_'.$a['TEST1'].'_'.$a['TEST2'];
}
sort($array_B);

$f = FALSE;
foreach($array_B as $a){
 if (ereg('.*_OK', $a)){
 if ($f)continue; else $f = TRUE;
 }else $f= FALSE;
 list($TEST3, $TEST1, $TEST2) = explode('_', $a);
 $res[] = array('TEST1'=>$TEST1, 'TEST2'=>$TEST2, 'TEST3'=>$TEST3);
}
◎質問者からの返答

ありがとうございます。


3 ● rudeboyjet
●26ポイント

最初の方の回答ですが

<?php
$ary = array(0 => array('TEST1' => 2222,
 'TEST2' => 'OK',
 'TEST3' => 8888),
 1 => array('TEST1' => 333333,
 'TEST2' => 'NG',
 'TEST3' => 9999),
 2 => array('TEST1' => 44444,
 'TEST2' => 'OK',
 'TEST3' => 777777));


function cmp($a, $b)
{
 if($a['TEST3'] == $b['TEST3']){
 return 0;
 }
 return ($a['TEST3'] < $b['TEST3']) ? -1 : 1;
}

usort($ary, 'cmp');
var_dump($ary);

二つめですが

<?php
$ary = array(0 => array('TEST1' => 2222,
 'TEST2' => 'OK',
 'TEST3' => 8888),
 1 => array('TEST1' => 333333,
 'TEST2' => 'NG',
 'TEST3' => 9999),
 2 => array('TEST1' => 44444,
 'TEST2' => 'OK',
 'TEST3' => 777777),
 3 => array('TEST1' => 44444,
 'TEST2' => 'OK',
 'TEST3' => 777777),
 4 => array('TEST1' => 2434,
 'TEST2' => 'NG',
 'TEST3' => 777777));

function compress_by_test2($ary, $product=NULL)
{
 if($ary == NULL){
 return $product;
 }

 if($product == NULL){
 $product = array();
 array_push($product, array_shift($ary));
 }
 $target = array_shift($ary);
 if($product[sizeof($product) - 1]['TEST2'] != $target['TEST2']){
 array_push($product, $target);
 }
 return compress_by_test2($ary, $product);
}

var_dump(compress_by_test2($ary));

二つめのほうはもっといいやりかたがあるかもしれませんが思い付きませんでした。

◎質問者からの返答

ありがとうございます。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ