PHPのshuffle()が連想配列では使えない件について

↓こんな連想配列があったとして、
$AmericanLeagueEastDivisionTeams = array(
    'BAL' => array('city' => 'Baltimore', 'name' => 'Orioles'),
    'BOS' => array('city' => 'Boston', 'name' => 'Red Sox'),
    'NYY' => array('city' => 'New York', 'name' => 'Yankees'),
    'TB' => array('city' => 'Tampa Bay', 'name' => 'Rays'),
    'TOR' => array('city' => 'Toronto', 'name' => 'Blue Jays'),
);

shuffle()してみると…
shuffle($AmericanLeagueEastDivisionTeams);
var_export($AmericanLeagueEastDivisionTeams);
↓結果(見やすいように整形済み)
array (
  0 => array ('city' => 'Boston', 'name' => 'Red Sox'),
  1 => array ('city' => 'Toronto', 'name' => 'Blue Jays'),
  2 => array ('city' => 'New York', 'name' => 'Yankees'),
  3 => array ('city' => 'Tampa Bay', 'name' => 'Rays'),
  4 => array ('city' => 'Baltimore', 'name' => 'Orioles')
)
はい。キーが破棄されて、数字キーに割り当て直されちゃいます。

じゃあ、array_rand()でランダム順のキーを取得しよう、と思った。
$len = count($AmericanLeagueEastDivisionTeams);
$abbrs = array_rand($AmericanLeagueEastDivisionTeams, $len);
var_export($abbrs);
↓結果
array (
  0 => 'BAL',
  1 => 'BOS',
  2 => 'NYY',
  3 => 'TB',
  4 => 'TOR',
)
よし、この「キーがランダム順に入った配列」を使おう。
…あれ?並べ変わってなくね?
たまたまかな(^o^;

再実行→やっぱりおんなじ→再々実行→やっぱりおんなじ→(無限ループ)
全件取得する場合は並べ換えて紅の豚?
マニュアルに書いといてよ。そんなこと。。

まあ、array_keys()を使ってそれをshuffle()すれば同じ事はできるか。
$abbrs = array_keys($AmericanLeagueEastDivisionTeams);
shuffle($abbrs);
var_export($abbrs);
↓結果
array (
  0 => 'NYY',
  1 => 'BOS',
  2 => 'TB',
  3 => 'BAL',
  4 => 'TOR',
)
当然ながらうまくいく。再実行すればまた並び変わる。

せっかくだから、関数化しておくか。
PHPオリジナルの命名則にあわせて、ashuffle()と名付ける(※)。
オリジナルのshuffle()が並べ替えが成功したかどうかを返しているので、とりあえずtrueを返すことにする。
function ashuffle(&$array) {
    $keys = array_keys($array);
    shuffle($keys);

    $res = array();
    for ($i = 0, $_l = count($keys); $i < $_l; $i++) {
        $res[$keys[$i]] = $array[$keys[$i]];
    }

    $array = $res;
    return true;
}

これで、
ashuffle($AmericanLeagueEastDivisionTeams);

$rank = 0;
foreach ($AmericanLeagueEastDivisionTeams as $abbr => $team) {
    printf("%d: %s %s (%s)¥n", ++$rank, $team['city'], $team['name'], $abbr);
}
↓結果

1: New York Yankees (NYY)
2: Baltimore Orioles (BAL)
3: Tampa Bay Rays (TB)
4: Boston Red Sox (BOS)
5: Toronto Blue Jays (TOR)
成功。


※:蛇足。
この記事を書く時に、そういえば、もうすでに誰かが作ってるよな。"ashuffle()"って名前で。
っと思ってググってみたら、どうやら無いみたい。。
ってことは、このページがひっかかるようになるんだ。ウシシ( ̄ー ̄)

PHP

— posted by たか at 12:12 am   pingTrackBack [0]

PHPSESSIDの無限ループ

Cookieが無効な環境のために、PHPのセッションID(デフォルトで"PHPSESSID")をURLに(クエリストリングとして)くっつけてリダイレクトする。
ということはモバイル向けサービスで良くあることだと思う。
んで、ローカルでテスト中、件の無限ループが発生した。
apacheのアクセスログを見ると、
hoge.php?foo=var
hoge.php?foo=var&amp;PHPSESSID=(SSID1)
hoge.php?foo=var&amp;amp;PHPSESSID=(SSID1)&amp;PHPSESSID=(SSID2)
...
hoge.php?foo=var&amp;amp;amp;amp;amp;amp;PHPSESSID=(SSID1)&amp;amp;amp;amp;amp;PHPSESSID=(SSID2)&amp;amp;amp;amp;PHPSESSID=(SSID3)&amp;amp;amp;PHPSESSID=(SSID4)&amp;amp;PHPSESSID=(SSID5)&amp;PHPSESSID=(SSID6)
...

すなわち、
hoge.php?foo=var
にアクセスがあって、セッションIDがついてないのでつけましょう。そしてリダイレクト。
hoge.php?foo=var&amp;PHPSESSID=(SSID1)
おやおや、セッションIDがついてないのでつけましょう。そしてリダイレクト。
hoge.php?foo=var&amp;amp;PHPSESSID=(SSID1)&amp;PHPSESSID=(SSID2)
っという具合に、無限に繰り返し、URL長エラーになるまで繰り返してた。っということ。

原因は、"&"であるべきセパレータが"&amp;"になっていること。
"PHPSESSID"のつもりが、"amp;PHPSESSID"になっちゃったわけだ。

さて、誰の仕業だろう?
プログラムで発行しているときにやっちまった?
Net_URLを使ってるから、この子のせい?
PHPが自動で付けたもの?
Apacheが変換した?

とまあ、色々調べてしまったよ。
結論を言うのは簡単だなぁ。。
その結論とは、
PHPの設定がヘンだった。それと、PHPの設定をNet_URLが忠実に読み込んでいたから。

Net_URL::getQueryString()で、クエリストリングのセパレータを、ini_get('arg_separator.output')で取ってきてます。

んで、オイラのWindowsなxampp環境では、php.iniファイルで下記の通り指定していた。
arg_separator.output = "&amp;"


むむむ。なんでこんなことしたんだっけ?
はい。これをコメントアウトして、サービスを再起動すると、…ちゃんと動いた。


以下、苦労した原因を箇条書きしておく。繰り返さないように(´・ω・`)
・デバッグ用にリダイレクトURLをHTML出力してみたわけだが、<textarea>タグ内ならば生のソースが表示されるハズ、と初歩的な勘違い
  → "&"と表示されて、うーん、ここまでは上手く行ってるのに…と誤解。実際は"&amp;"だったのに
・php.iniを書き換えたら即時適用されそうな気がしていた
  → apacheを最起動しないと読まないよ。Windowsの場合サービスの再起動が必要。
・php.iniを変更するなら、なぜそうしたかメモっておこうよ。。
・グーグル先生を過信し過ぎ(←あえて冗長表現してみた)。

PHP

— posted by たか at 03:27 pm   pingTrackBack [0]

 

BroadcastReceiverが勝手に止まってしまう件について

BroadcastReceiverを使って、ほとんどすべてのブロードキャストを受け取ってToastでポップアップ表示する。
という、うっと惜しい(なぜか変換できない)Widgetを作ってみたLink わけだが、いつの間にか勝手に泊まる。いや、止まる。

さて、グーグル先生に相談だ(音符

BroadcastReceiverに寿命があって、寿命が尽きたことを知る手段でもあるのではないかと探したんだけど、うまくいかない。
んで、それは置いておいて、別件でサービスについて調べてたんだけど、
…これは、という情報があった。

こちらに曰く、

Android は、メモリが少なくなってくると...サービスも止められてしまうことがある
...
システムがサービスを停止させた場合、メモリに余裕が出来るとシステムが再度起動してくれる
ああ、そんなこと聞いたことある。聞いたんじゃなくて読んだんだけど。<どうでもいいだろ

システムから起動された時は Service::onStart は呼ばれず、Service::onCreate までしか呼ばれない
これだ(゚∀゚)!
確かに、ServiceのonStartでBroadcastReceiverをregisterReceiverしておった。
onCreateでレジストしてもよかろうもんがじゃ。
これで、止まっても復活してくれるのかなぁ。

やってみるけど、いつ勝手に止まるか、そしていつ再起動するかがわからないから、テストがムズイね┐(´д`)┌

ウィジェット アンドロイド

— posted by たか at 12:15 am   pingTrackBack [0]

秒を表示するアンドロイドウィジェット(試作apk)

某ブログですでに公開済み(ただし、アクセス数ほぼゼロ)ですが…。
秒を表示するウィジェットを作ってみた。
スクリーンショット
スクリーンショット

機能としては、こんなところです。
・年月日時分と、電池レベル・温度・状態を表示します。
・ウィジェットをタッチした時のみ秒を表示します。
・電池状態が変わった時に表示を更新します。
・いろんなイベントでも表示を更新します。その場合はイベントの種類を表す文字列を表示します。また、同文字列をポップアップします。
・自分用デザインなので、表示箇所が偏ってます。
・きっと種々の不具合を抱えています。
・マーケットには登録しませんので、apkファイルからのインストールとなります。

こんなものが欲しい人は居ないと思うけど、どうぞ。
(次のページにあります…アクセス解析のためです(ノ´∀`*))

ところで、某ブログにも書きましたが、真面目に使うなら、こっちのほうが良いですよ。
画面を点けたら秒時計(マーケット)Link
スリープ状態から画面点灯した時のみ、通知領域に時分秒の時計をしばらく表示してくれます。ロック解除しなくても見られるのがステキですね。…ワタシも使ってます(^o^;

1 of 3123Next»

ウィジェット アンドロイド

— posted by たか at 09:05 pm   pingTrackBack [0]

jQueryバージョンアップで使えなくなるセレクタ

ほとんど↓の記事のパクリですが。。。
jQuery 1.4.4 で使えなくなってるセレクタ - m2Link

まあ、検索にヒットしやすくなるということで書きます。

htmlでこんなフォーム部品があって、その値をjQueryで使用する場合。
<input type="text" name="arr[key]" size="8" />

なにかの都合で、PHPなどでフォーム値を配列として取得したいな、というわけで、
name属性に配列を指定しています。
ここがミソ。

jQueryで取得はこうしていた訳だが(ホントは"["や"]"などの記号はエスケープしなきゃいけないみたいだけど…)
var val=$(":input[name=arr[key]]").val();

これが、jQuery1.5にしたら動かなくなった。

どうすればいいのかというと、とりあえず↓のようにすれば動きました。
var val=$(":input[name='arr[key]']").val();

つまり、「foo='var'」と、右辺をクォートすればよいようです。
やってみてないけど、シングルとダブルクォーテーションを入れ替えてもよいと思われ。
var val=$(':input[name="arr[key]"]').val();

jQuery

— posted by たか at 09:48 pm   pingTrackBack [0]

T: Y: ALL: Online:
ThemeSwitch
Created in 0.1346 sec.
prev
2017.3
next
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
 
blogBar
Firefox3 Meter