質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

7221閲覧

array_mapとarray_walkの違い

SugiuraY

総合スコア317

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

1グッド

2クリップ

投稿2016/11/09 04:28

編集2016/11/09 04:29

お世話になります。

もろもろ調べたのですが、なかなか納得ができません。
掲題の配列の要素をそれぞれ2倍にする関数ですが

  1. array_walkはもとの配列の変数$arrayのままで、function適用後の値(2倍かけた値)が得られ、一方array_mapは

$array2に格納して出力しなければfunction適用後の値(2倍かけた値)が得られないのは、walkは破壊的メソッドでmapは非破壊的メソッドであるからという理解であっていますでしょうか?

2)なぜ、コールバック関数の中身が$item= $item2;とreturn $item2;と違いが生じるのかがそれぞれの関数の仕様からいまいち理解ができません。なんとなくmapのほうが理解できるのですが、walkはマニュアルを見ると返り値として「成功した場合に TRUE を、失敗した場合に FALSE を返します。」と説明がされています。この違いからくるのでしょうか?

3)2)に関連してですが、そもそも成功と失敗とは何を指しているのでしょうか?

4)2)に関連してですが、このコールバック関数でtrueやfalseを返すことに全く意味がないように思えるのですが。。配列の値やkeyに関数を適用する意図があって作られたwalkやmapであると理解しているのですが、まったくarray_walkの意味がないような気がしてならないのですが、どのようなケースを想定してる関数(これでなくては処理できない?)なのでしょうか?
もし具体的な例とかがあれば。。

なにとぞ、宜しくお願い申し上げます。

walk <?php $array=array(5,10); function twice (&$item) { $item= $item*2; } array_walk($array,'twice'); var_dump($array); ?>
map $array=array(5,10); function twice ($item) { return $item*2; } $array2=array_map('twice',$array); var_dump($array2); ?>
miyabi-sun👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

array_maparray_walk

array_map — 指定した配列の要素にコールバック関数を適用する
array_walk — 配列の全ての要素にユーザー定義の関数を適用する

違いが全然分からない・・・・これは公式が言葉足らずですね。
引数や戻り値のUsage的なアレを見ればarray_walkは破壊メソッドなのはかろうじてわかりますが・・・・

そもそもmapという名称は地図を連想するかと思いますが、
工場でプレス加工して一度に大量の製品を作る事もmapと呼ばれるそうです。
そこから転じて、配列の中身に同じ処理を加えて加工後の値を一気に取り出す事を指すそうです。

mapは関数型プログラミングのList操作に属するもので、
高階関数 map等のワードでググると関数型プログラミングでは一般的に使用される関数として紹介されています。
特徴は大体こんな感じ

  • 非破壊メソッドである
  • 関数を引数として要求する
  • 戻り値に加工後の配列を返す
  • 加工前と加工後の配列は要素数は一致する

下記がJavaScriptでの実装の一例です。
PHPのarray_mapとは少し違いますが、Arrayに内蔵されているmapメソッドを利用して実現しています。

JavaScript

1var twice = function (it) { return it * 2; }; 2var arr = [1, 2, 3].map(twice); 3console.log(arr); 4// [2, 4, 6]

逆にwalkは何者なんでしょうね?
foreachが言語構造として実装されてしまっているので要らない関数にしか見えません。
(一応array_walk_recursiveまでいけば役に立つと思うのですが…)


「追記部分」

レスを読んでいると下記の記事がお役に立ちそうなので、共有します。
array_mapにありがとう、さよなら
部分適用ってなんだ

コールバック関数による配列操作はそもそもPHPに必要ありません。
関数型プログラミングをやるにはPHPは不向きだと私は思っています。
foreachという万能言語構造がありますから、やりたいことの大多数は高階関数がなくてもできます。

array_mapとforeach、array_walk等を無理に混ぜると、コードが読みづらくなる可能性は高いです。
コードの見通しを良くする為に関数型プログラミングの書き方で統一するくらいなら、
最初からScalaのような関数型言語を使えば良いじゃないかと考えます。

ChatWorkも最初はPHPで、後に全サービスをScalaで書き直したそうです。
ただし、将来PHPもJavaからスピンオフしたScalaみたいな言語が生まれるかもしれませんね。

投稿2016/11/09 07:23

編集2016/11/09 08:41
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2016/11/09 07:40

ご回答いただき、有難うございます! そうなんですよ~、、しかもforeachのほうが処理も早く、、、、一体配列の中をwalkして破壊だけして去っていくこの関数の存在意義を見出せません。recursiveは確かにお世話になっております。
guest

0

間違ったコメントを修正さました。

投稿2016/11/09 07:30

編集2016/11/09 07:32
SugiuraY

総合スコア317

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

難しい質問ですね。。。

1

array_walkは破壊的メソッドでarray_mapは非破壊的メソッドの理解で良いと思います。

2

array_walkは破壊的という事で内部のコールバック関数の中で与えられた引数の配列のアドレスそのものに操作をしているのだろうと思います。(思いますというのは実際のphpのソース読みかけましたが、時間かかりそうなのでやめました、あとで参考にURL載せておきます)質問者様のソースもそういうコールバックになってますよね?上書きっぽい処理に
対して
array_mapは非破壊的なのでコールバックの引数のアドレスそのものではなくもとの値は変えずに処理してますよね?

3

これが一番難しい、、何をもって成功・失敗にするか、正確に何を成功・何を失敗としてあつかっているかはソース見ないとわかりません。。。

https://github.com/php/php-src

https://github.com/php/php-src/blob/master/ext/standard/array.c
の中にphp_walkのソースがありますが、マクロまみれで読むのに時間かかりそうでやめましたが気になるなら是非

4

array_walkの操作はほぼforeachで実現可能です。

foreach($array as $key=>$val) $array[$key] = $val * 2;

ただし、こんな資料がありました。
https://www.reddit.com/r/PHP/comments/1uuc34/quick_test_to_see_if_array_walk_is_better_than/
とか
https://eval.in/87941
https://eval.in/87942
とか

foreachの方が早いですね。。。。
特に優位性見出せないです。

###追記

いつのまにかarray_walkとforeach比較の回答になってました、重要な点

配列の値やkeyに関数を適用する意図があって作られたwalkやmapであると理解しているのですが、array_walkの意味がないような気がしてならないのですが、どのようなケースを想定してる関数(これでなくては処理できない?)なのでしょうか?

に関しては大きな違いは1にある通り元の配列も残すか、残さないかの違いです。これは大きな違いで配列の各要素になんらかの処理をしたい(ここまでは同じ)が元の配列も後でつかうので残しておかなくてはならないならmap、上書き上書きで後ろを振り向かなくていいならwalkといったところでしょうか。

投稿2016/11/09 05:55

編集2016/11/09 06:29
hiim

総合スコア1689

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2016/11/09 07:31

ご親切にご回答を頂き、誠に有難うございます。あまりのご丁寧さに涙です。 一点だけ気になったのですが、 >array_walkの操作はほぼforeachで実現可能です。 と仰って頂き、良くこのお話も聞くのですが、array_mapも、各配列要素や添字に定義関数を適用できるという意味では、foreachで代用できるきがするのですが。。 もちろん、破壊的メソッドという点では、全く結果は異なるとおもいます。
hiim

2016/11/09 07:41

はい、array_mapもforeachで代用できると思います。これを書いてしまうと反対意見とかもでそうですが、phpの標準関数すべてが有用な関数で、本当に必要な関数とは思えないです。私個人的には今回の質問の操作をする場合まずarray_map、array_walk関数を使わないです。というより私自身ほとんどこれらの関数使った場面おもいだせません。
SugiuraY

2016/11/09 07:44

コメントありがとうございます。 ある意味で一番明解なご回答だと思います。便利なのか不便なのか、マニュアル見ながら眉間にしわを寄せていたので、あまり微妙な組込関数には首を突っ込まないほうが良いかもしれません。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問