iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 4
0
自我挑戰組

花式PHP系列 第 4

Array:流程控制、迭代操作

/images/emoticon/emoticon35.gif

接下來要介紹 PHP 陣列函式整整六天~
如果你覺得 foreachfor+count() 就能打遍天下,請一定要看看這系列文章!

使用 PHP 自己提供的陣列函式
除了可以使你對陣列的操作更語意化,還能讓別人更清楚你這段程式碼的目的在哪~
有學習過這些函式的工程師一定都能一眼看懂你想作什麼的!

正片開始

in_array

in_array 可以幫你檢查陣列中有沒有指定的資料存在。

比如說,
有一天你去買紅豆餅,
你已經想好你要吃奶油口味的了,但你還是需要問他有賣什麼口味,
你知道老闆賣的口味之後,就要想想其中有沒有包含奶油口味才決定要不要購買~

<?php

/*
 * 你的參數
 */
$stomach = [];
$moneyInPocket = 200;
$targetType = '奶油';
$amount = 2;

/*
 * 攤販的參數
 */
$priceEachWheelPie = 10;
$types = [
    '紅豆',
    '奶油',
    '南瓜',
    '芋頭',
    '羅蔔絲',
    '珍珠',
];

if (in_array($targetType, $types)) {
    $moneyInPocket -= $priceEachWheelPie * $amount;
    
    for ($amountEaten = 0; $amountEaten < $amount; $amountEaten++) {
        $stomach[] = "{$targetType}車輪餅";
    }
}

print_r($stomach);

array_key_exists

array_key_exists 作的事情其實跟 in_array 差不多,
不過對象不一樣,前者是對 array key(index) 作比對;後者是對 array values

除了在買紅豆餅的時候你會需要用到這個函式 ~
在有些要動態決定程式行為的場合也用的到~

比如說有個能送出 http request 的 function curl($request, $params = []) {}
在有設定 $params['method'] 的時候會送出使用指定方法的 http request

上面的例子改寫一下就可以了:

<?php

/*
 * 你的參數
 */
$stomach = [];
$moneyInPocket = 200;
$targetType = '奶油';
$amount = 2;

/*
 * 攤販的參數
 * type => price each wheel pie
 */
$types = [
    '紅豆' => 10,
    '奶油' => 20,
    '南瓜' => 30,
    '芋頭' => 40,
    '羅蔔絲' => 50,
    '珍珠' => 60,
];

if (array_key_exists($targetType, $types)) {
    $moneyInPocket -= $types[$targetType] * $amount;
    
    for ($amountEaten = 0; $amountEaten < $amount; $amountEaten++) {
        /*
         * @see http://php.net/manual/en/function.array-push.php
         */
        array_push($stomach, "{$targetType}車輪餅");
    }
}

print_r($stomach);

array_map

array_map 通常用在你單純需要取出陣列中的部份資料,或取出轉換過的資料的時候。

比如說你在買紅豆餅之前(這次你沒有特別想吃的口味),
需要估計每種口味買 2 個的話各是需要花多少錢,那就可以這樣計算:

<?php

$amount = 2;

/*
 * type => price each wheel pie
 */
$types = [
    '紅豆' => 10,
    '奶油' => 20,
    '南瓜' => 30,
    '芋頭' => 40,
    '羅蔔絲' => 50,
    '珍珠' => 60,
];

/*
 * 從 callback 外部引入變數
 * @see http://php.net/manual/en/functions.anonymous.php#example-165
 */
$estimatePrices = array_map(function ($price) use ($amount) {
    return $price * $amount;
}, $types);

print_r($estimatePrices);

上面這段程式碼等價於:

<?php

$amount = 2;

/*
 * type => price each wheel pie
 */
$types = [
    '紅豆' => 10,
    '奶油' => 20,
    '南瓜' => 30,
    '芋頭' => 40,
    '羅蔔絲' => 50,
    '珍珠' => 60,
];

/*
 * 從 callback 外部引入變數
 * @see http://php.net/manual/en/functions.anonymous.php#example-165
 */
$estimatePrices = [];

foreach ($types as $type => $price) {
    $estimatePrices[$type] = $price * $amount;
}

print_r($estimatePrices);

array_walk

array_walk 與 array_map 一樣都是對陣列做一個迭代的動作,
但其中最大的差別在:

  1. array_walk 的callback中可以直接對傳入的array做修改(也可以不要,取決於 & 運算符)
  2. array_walk 執行完僅回傳bool而不是array(主要目的是操作)
  3. array_walk 與 array_map 傳入被操作的$array的位置不一樣

這兩點差別就造成了 array_walk 與 array_map 適用場景的不同!

下面這段程式碼主要在把紅豆餅的價錢後面,都加上「元」這個字:
(你們可以試試看把 $value 前面的 & 移除掉,比較移除前後的差別)

<?php

$types = [
    '紅豆' => 10,
    '奶油' => 20,
    '南瓜' => 30,
    '芋頭' => 40,
    '羅蔔絲' => 50,
    '珍珠' => 60,
];

array_walk($types, function (&$value, &$key) {
    $value = "{$value}元";
});

print_r($types);

而上面這段程式碼等價於:

<?php

$types = [
    '紅豆' => 10,
    '奶油' => 20,
    '南瓜' => 30,
    '芋頭' => 40,
    '羅蔔絲' => 50,
    '珍珠' => 60,
];

foreach ($types as $key => &$value) {
    $value = "{$value}元";
}

print_r($types);

坦白說,
從精進程式碼語意化的目標來說,
這邊 array_walk 改進的效果不如 array_map 明顯,甚至還不如 foreach 本身。

我個人大部分時候也還是偏向使用 foreach 而不是 array_walk,
還是各位如果有什麼想法也歡迎在留言處告訴我,謝謝大家~


上一篇
關聯陣列、花式函式宣告與呼叫
下一篇
Array:排序
系列文
花式PHP31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言