2012-07-19 111 views
13

我已經習慣了Perl的地圖,其中所述回調可以分配兩個鍵和值,從而產生一個關聯數組,其中輸入是一個平面陣列()函數。我所知道的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" />其中每個這種類型的字段的帶有前綴「現場」。

我們想要做的是,首先,得到的只是究竟是誰開始與「現場」,那麼,我們要創建一個關聯數組叫做$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 2012-07-19 14:39:53

+1

@Florent done ... – 2012-07-19 18:07:49

回答

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 - 搞清楚它總是隻是返回一個標量值。回想起來,這種方法是否比上面提到的@minitech提到的foreach方法更可取。但很高興看到你的選擇!感謝發佈。 – 2012-11-20 15:51:25

+0

聰明的方法。這通常非常方便 – Ikke 2012-12-17 11:37:23

+0

我實際上同意湯姆奧格,這是值得懷疑的,如果一個人應該使用這種方法。即使你在性能方面獲勝(我不確定),但與通常的foreach聲明相比,你的可讀性較差。雖然優雅;) – 2012-12-18 07:24:20

2

據我所知,在一個表達式中是完全不可能的,所以你可能會以及使用foreach環,點菜

$new_hash = array(); 

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

如果你需要在一個表情,繼續前進,使一個功能:

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

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

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

    return $result; 
} 
2

這是我在接受的方法註釋了澄清。希望更容易閱讀。這是一個WordPress類,因此WPDB $參考寫入數據:

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代碼來說,這是我的一個解決方案,即使在生產項目中也是如此。很好,謝謝你回來提供另一種解決方案。 – 2013-03-11 13:29:27