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

PHP初心者です。
csvデータから読み込んだデータをもとに、連想配列をソートしたいと考えています。
一行にたとえば
みかん,580,りんご,240,ぶどう,360,くり,110
といったかたちで、データが入っていて、複数行あります。
まず、各行内を
みかん=>580 といったかたちで、果物名をkey、値段をvalueにしていき、
さらに、それらをvalueの値順(値段が高い順)にソートして表示していきたいのですが、変数?を連想配列にする方法がわからず困っています。
また、各行の長さ(種類数)は一定ではなく、この処理を全行にわたって繰り返し行いたいと思っています。

漠然としていて申し訳ないのですが、、ざっくりとした流れと、連想配列部分の具体例について教えていただけないでしょうか。。。
よろしくおねがいいたします。

●質問者: inkyo
●カテゴリ:ウェブ制作
✍キーワード:360 CSV Key PHP ぶどう
○ 状態 :終了
└ 回答数 : 4/5件

▽最新の回答へ

1 ● KUROX
●35ポイント

これがもしかしてつかえるかも

http://www.res-system.com/item/508

自前でやりたいのなら、このあたりを参考にして

もう少し考えてみては

http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/php_k08.htm


2 ● GEN111
●35ポイント

やり方はいろいろあると思いますが、例として


オーソドックスな感じ

<?php
$datafile = './data.csv' ; // CSV ファイル

$fh = fopen($datafile, 'r') ;
if ($fh) {
 flock($fh, LOCK_SH) ;

 $lst = array() ;
 while ($line = fgets($fh)) { // ファイルから一行ずつ読み込む
 $all = explode(',', chop($line)) ; // カンマで分割して配列に

 while (($key = array_shift($all)) && ($val = array_shift($all))) { // 配列の先頭から名前と値を取り出す
 $lst{$key} = $val ; // 連想配列にセット
 }
 }

 // ソートして表示
 asort($lst) ;
 echo '<pre>' ;
 print_r($lst) ;
 echo '</pre>' ;

 flock($fh, LOCK_UN) ;
 fclose($fh) ;
}
?>

正規表現を使って

while ($line = fgets($fh)) { // ファイルから一行ずつ読み込む
 preg_replace('/([^,]+),([^,]+)/e', '$lst[$1] = $2;', $line) ;
}

key,val,key,val ... のペアになってない場合は考慮していません。

PHP: 配列 - Manual


3 ● tezcello
●10ポイント

ある変数に収められている値(群)を連想配列にする方法 という事なので、こんなのはどうでしょう?


名前と値段のペアが何組あるか分らないので、preg_match_all でペア毎に取り出します。

後は、取り出したペア全てで連想配列に入れてやるだけです。

$source = file('ファイル名');
foreach($source as $str){{
 preg_match_all('/([^,]+),(\d+)/', $str, $res, PREG_SET_ORDER);
 foreach($res as $r) $lst[$r[1]] = $r[2];
}
arsort($lst);

(参考)http://www.php.net/manual/ja/function.preg-match-all.php

日本語のコードはEUCかUTF-8でないと果物名を直接キーには出来ませんので、ご注意を。

また、果物名に重複がある場合を考慮していません。


preg_match_all() の部分を明確にするために、ファイルの内容を配列に取り込んでいるでわざわざ2回 foreach を使っていますが、

file_get_contents() 等で一つの変数に入れてしまう事で1回でもできます。

その際は改行文字を無視するようなパターンを変更すればOKです。(CSVファイルにあわせて下さい)

$str = file_get_contents('ファイル名');
preg_match_all('/([^,\n]+),(\d+)/', $str, $res, PREG_SET_ORDER);
foreach($res as $r) $lst[$r[1]] = $r[2];

arsort($lst);

4 ● tobeoscontinue
●10ポイント

すべきことは

1.csvデータから読み込む

2.連想配列に変換する

3.ソートする。

の三つです。

<?php
$hash = array();
function chunk_combine($value, $key) {
global $hash;
$hash[$value[1]] = $value[0];
}

$files = file("data.csv");
$datas = implode (',', $files);
$datas = str_replace("\n", '', $datas);

$data_a = explode(',', $datas);
$chunk = array_chunk($data_a, 2);
array_walk($chunk, 'chunk_combine');
asort($hash);
print_r($hash);
?>

1.の読み込みはfile()が面倒がなく、簡単です。がこの場合、行単位の配列になります。

そこでimplode()を使って全てを連結して長い文字列にしてしまいます。このままでは行のlfが残っているのでstr_replace()で取り除きます。

2.がちょっと面倒で、定石があるのかもしれませんが解からないのでarray_walk()を使ってみました。foreachの方がわかりやすいんだけど。

まず長い文字列($datas)をexplode()を使って,で区切って配列にします。次にarray_chunk()で2個づつのペアの配列にします。array_walk()はforeachと同じような目的で使ってますが2個づつのペアが取り出されてchunk_combine()が実行されるので、その中のグローバルな$hashに追加しています。chunk_combine()の中で更新結果を返すいい方法がわからなかったのでグローバルを使ってます。

3.のソートは幾つかあるので目的に合わせて替えればいいでしょう。

少し助長なのですこしまとめると下記になります。

<?php
$hash = array();
function chunk_combine($value, $key) {
global $hash;
$hash[$value[1]] = $value[0];
}

$datas = str_replace("\n", '', implode (',', file("data.csv")));

array_walk(array_chunk(explode(',', $datas), 2), 'chunk_combine');
asort($hash);
print_r($hash);
?>

http://jp.php.net/manual/ja/ref.array.php

関連質問


●質問をもっと探す●



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