2012-07-19 14 views
13

私は、コールバックがキーと値の両方を割り当てることができるperlのmap()関数に慣れています。そのため、入力がフラットな配列だった連想配列が作成されます。私はarray_fill_keys()を知っています。これは、辞書スタイルのハッシュを作成するだけの場合に便利ですが、必ずしもすべての値を同じにする必要がない場合はどうしたらいいですか?明らかにすべてのことはforeach反復で行うことができますが、他の(おそらくよりエレガントな)メソッドは存在しますか?配列またはオブジェクトの配列を連想配列に変換するにはどうすればよいですか?

:変換を明確にするための例を追加してください。変換でハングアップしないでください。問題は、フラットリストをハッシュに変換することです。ここでは、すべての値が同じであるとは仮定できません。

$original_array: ('a', 'b', 'c', 'd') 
$new_hash: ('a'=>'yes', 'b'=>'no', 'c'=>'yes', 'd'=>'no') 

*note: the values in this example are arbitrary, governed by some business logic that is not really relevant to this question. For example, perhaps it's based on the even-oddness of the ordinal value of the key 

実世界の例 だから、ここに提供された答えを使用して、ここで指定した条件に一致するのみの入力フィールドのリストを取得するには$ _POSTのを解析できる方法です。たとえば、フォームに多くの入力フィールドがあるが、それらの特定のグループを一緒に処理する必要がある場合など、これは便利です。

この場合、データベースへのマッピングを表すいくつかの入力フィールドがあります。各入力フィールドは次のようになります。 <input name="field-user_email" value="2" />このフィールドの各フィールドには、「field-」という接頭辞が付きます。

実際に "field-"で始まる入力フィールドのリストを取得してから、抽出したフィールド名をキーとして持つ$mapped_fieldsという連想配列を作成し、値としての実際の入力フィールドの値

出力
$mapped_fields = array_reduce(preg_grep('/field-.+/', array_keys($_POST)), function($hash, $field){ $hash[substr($field, 6)] = $_POST[$field]; return $hash; }); 

Array ([date_of_birth] => 1 [user_email] => 2 [last_name] => 3 [first_name] => 4 [current_position] => 6) 

を(だから、私だけは、コンパクトなコードのこのビットは、$ _POSTて単純なループ反復することそれは間違いなくはるかに少ない読み取り可能であることに同意しましょう、否定派を未然に防ぐためにキーごとにプレフィックスがあるかどうかを確認し、そうであれば、その値を配列にポップします)

+0

'print_r'や' var_dump'を使って配列のダンプを投稿できますか? – Florent

+1

@Florent done ... –

答えて

29

私はいくつかの日前とまったく同じ問題を抱えていました。 array_mapを使用することはできませんが、array_reduceはそのトリックを行います。

$arr = array('a','b','c','d'); 
$assoc_arr = array_reduce($arr, function ($result, $item) { 
    $result[$item] = (($item == 'a') || ($item == 'c')) ? 'yes' : 'no'; 
    return $result; 
}, array()); 
var_dump($assoc_arr); 

結果:

array(4) { ["a"]=> string(3) "yes" ["b"]=> string(2) "no" ["c"]=> string(3) "yes" ["d"]=> string(2) "no" }

+1

このようにarray_reduceを使うことは決してありませんでした。それは常にスカラー値を返すことを意味していました。振り返ってみると、このアプローチが上記のforeachメソッド@minitechの記述よりも好ましい方法であるかどうかは疑問だ。しかし、あなたの選択肢を見て非常にいいです!投稿していただきありがとうございます。 –

+0

巧妙な方法。これはしばしば非常に便利です。 – Ikke

+0

私はTom Augerと実際に同意しています。このメソッドを使うべきかどうかは疑問です。あなたがパフォーマンス面で勝ったとしても(私にはわかりませんが)、通常のforeachステートメントに比べて読みやすさが緩いです。エレガントだが;) –

2

私の知る限り、1つの式では完全に不可能です。よくforeachループを使用して、

$new_hash = array(); 

foreach($original_array as $item) { 
    $new_hash[$item] = 'something'; 
} 

使用すると、1つの式、先に行くと機能を作るにはそれが必要な場合:

function array_map_keys($callback, $array) { 
    $result = array(); 

    foreach($array as $item) { 
     $r = $callback($item); 

     $result[$r[0]] = $r[1]; 
    } 

    return $result; 
} 
2

これが認められた方法で私のコメントの明確化です。うまくいけば読みやすくなります。これは、このように$のwpdb参照がデータの書き込みに、WordPressのクラスからです:

class SLPlus_Locations { 
    private $dbFields = array('name','address','city'); 

    public function MakePersistent() { 
     global $wpdb; 
     $dataArray = array_reduce($this->dbFields,array($this,'mapPropertyToField')); 
     $wpdb->insert('wp_store_locator',$dataArray); 
    } 

    private function mapPropertyToField($result,$property) { 
     $result[$property] = $this->$property; 
     return $result; 
    } 
} 

が明らかに完全なソリューションにもう少しそこにあるのが、array_reduceに関連する部分は、()が存在します。 foreachよりも読みやすく、より洗練されています。また、array_map()とカスタム挿入ステートメントを使用して問題を強制します。

ニース!

+0

ワンライナーとPerlスタイルのobfuコードのためのちょっとした吸盤だから、これは私のゴー・ツー・ソリューションです。ニースの方、もう一度解決策を提供してくれてありがとう。 –

関連する問題