array_combine()
(PHP 5, PHP 7)
创建一个数组,用一个数组的值作为其键名,另一个数组的值作为其值
说明
array_combine(array $keys,array $values): array
返回一个array,用来自$keys数组的值作为键名,来自$values数组的值作为相应的值。
参数
- $keys
将被作为新数组的键。非法的值将会被转换为字符串类型(string)。
- $values
将被作为Array的值。
返回值
返回合并的array,如果两个数组的单元数不同则返回FALSE
。
错误/异常
如果作为$keys的数组和作为$values的数组的元素个数不一样,将会抛出一个警告错误(E_WARNING
)。
更新日志
版本 | 说明 |
---|---|
5.4.0 | (修复)早期版本中如果是空数组就报E_WARNING 的错并且返回FALSE 。 |
范例
一个array_combine()简单的例子
<?php $a = array('green', 'red', 'yellow'); $b = array('avocado', 'apple', 'banana'); $c = array_combine($a, $b); print_r($c); ?>
以上例程会输出:
Array ( [green] => avocado [red] => apple [yellow] => banana )
参见
array_merge()
合并一个或多个数组array_walk()
使用用户自定义函数对数组中的每个元素做回调处理array_values()
返回数组中所有的值
If two keys are the same, the second one prevails. Example: <?php print_r(array_combine(Array('a','a','b'), Array(1,2,3))); ?> Returns: Array ( [a] => 2 [b] => 3 ) But if you need to keep all values, you can use the function below: <?php function array_combine_($keys, $values) { $result = array(); foreach ($keys as $i => $k) { $result[$k][] = $values[$i]; } array_walk($result, create_function('&$v', '$v = (count($v) == 1)? array_pop($v): $v;')); return $result; } print_r(array_combine_(Array('a','a','b'), Array(1,2,3))); ?> Returns: Array ( [a] => Array ( [0] => 1 [1] => 2 ) [b] => 3 )
Further to loreiorg's script in order to preserve duplicate keys when combining arrays. I have modified the script to use a closure instead of create_function Reason: see security issue flagged up in the documentation concerning create_function <?php function array_combine_($keys, $values){ $result = array(); foreach ($keys as $i => $k) { $result[$k][] = $values[$i]; } array_walk($result, function(&$v){ $v = (count($v) == 1) ? array_pop($v): $v; }); return $result; } ?>
array_combine() has a strange bug/misfeature (as of PHP 5.3.2): There is no logical reason for <? array_combine(array(), array()) ?> throwing a warning and returning FALSE, instead of returning <? array() ?> (see http://bugs.php.net/bug.php?id=34857). Here is a quick workaround: <?php function array_real_combine($a, $b) { return $a===array() && $b===array() ? array() : array_combine($a, $b); } ?>
<?php // If they are not of same size, here is solution: $abbreviations = array("AL", "AK", "AZ", "AR", "TX", "CA"); $states = array("Alabama", "Alaska", "Arizona", "Arkansas"); function combine_arr($a, $b) { $acount = count($a); $bcount = count($b); $size = ($acount > $bcount) ? $bcount : $acount; $a = array_slice($a, 0, $size); $b = array_slice($b, 0, $size); return array_combine($a, $b); } $combined = combine_arr($abbreviations, $states); print_r($combined); // Output // Array ( [AL] => Alabama [AK] => Alaska [AZ] => Arizona // [AR] => Arkansas ) ?>
I recently had to flip an array and group the elements by value, this snippet will do that: <?php function flipAndGroup($input) { $outArr = array(); array_walk($input, function($value, $key) use (&$outArr) { if(!isset($outArr[$value]) || !is_array($outArr[$value])) { $outArr[$value] = []; } $outArr[$value][] = $key; }); return $outArr; } ?> Example: <?php $users_countries = array( 'username1' => 'US', 'user2' => 'US', 'newuser' => 'GB' ); print_r(flipAndGroup($users_countries)); ?> Returns: Array ( [US] => Array ( [0] => username1 [1] => user2 ) [GB] => Array ( [0] => newuser ) )
I needed to read CSV files into associative arrays with column headers as keys. Then I ran into a problem when you have empty columns at the end of a row because array_combine returns false if both arrays don't have the same number of elements. This function based on quecoder at gmail's combine_arr() below allowed me to pad either array or not when parsing my CSVs to arrays. $a is the array of header columns and $b is an array of the current row retrieved with fgetcsv() <?php function array_combine_special($a, $b, $pad = TRUE) { $acount = count($a); $bcount = count($b); // more elements in $a than $b but we don't want to pad either if (!$pad) { $size = ($acount > $bcount) ? $bcount : $acount; $a = array_slice($a, 0, $size); $b = array_slice($b, 0, $size); } else { // more headers than row fields if ($acount > $bcount) { $more = $acount - $bcount; // how many fields are we missing at the end of the second array? // Add empty strings to ensure arrays $a and $b have same number of elements $more = $acount - $bcount; for($i = 0; $i < $more; $i++) { $b[] = ""; } // more fields than headers } else if ($acount < $bcount) { $more = $bcount - $acount; // fewer elements in the first array, add extra keys for($i = 0; $i < $more; $i++) { $key = 'extra_field_0' . $i; $a[] = $key; } } } return array_combine($a, $b); } ?>
If two keys are the same, the second one prevails. Example: <?php print_r(array_combine(Array('a','a','b'), Array(1,2,3))); ?> Returns: Array ( [a] => 2 [b] => 3 )
This will seem obvious to some, but if you need to preserve a duplicate key, being you have unique vars, you can switch the array_combine around, to where the vars are the keys, and this will output correctly. This [default] formula auto-removes the duplicate keys. $i=0; foreach (array_combine($keys, $vars) as $key => $var) { $i=$i; echo($key); echo " "; echo($var); } This formula accomplishes the same thing, in the same order, but the duplicate "keys" (which are now vars) are kept. $i=0; foreach (array_combine($vars, $keys) as $var => $key) { $i=$i; echo($key); echo " "; echo($var); } I know, I'm a newbie, but perhaps someone else will need this eventually. I couldn't find another solution anywhere.
I needed a function that truncated extra values, and only went as far as keys without throwing a warning as array_combine does. <?php function safeArrayCombine($keys, $values) { $combinedArray = array(); for ($i=0, $keyCount = count($keys); $i < $keyCount; $i++) { $combinedArray[$keys[$i]] = $values[$i]; } return $combinedArray; } ?>
I needed a function that would take keys from one unequal array and combine them with the values of another. Real life application: Select 4 product types. Each product has a serial. There are 4 sets of products. <?php function array_combine2($arr1, $arr2) { $count1 = count($arr1); $count2 = count($arr2); $numofloops = $count2/$count1; $i = 0; while($i < $numofloops){ $arr3 = array_slice($arr2, $count1*$i, $count1); $arr4[] = array_combine($arr1,$arr3); $i++; } return $arr4; } ?> Input: Array ( [0] => SMART Board [1] => Projector [2] => Speakers [3] => Splitter ) , Array ( [0] => serial to smart board1 [1] => serial to projector 1 [2] => serial to speakers 1 [3] => serials to splitter 1 [4] => serials to smart board 2 [5] => serials to projector 2 [6] => serials to speakers 2 [7] => serials to splitter 2 ) Array ( [0] => Array ( [SMART Board] => serial to smart board1 [Projector] => serial to projector 1 [Speakers] => serial to speakers 1 [Splitter] => serials to splitter 1 ) [1] => Array ( [SMART Board] => serials to smart board 2 [Projector] => serials to projector 2 [Speakers] => serials to speakers 2 [Splitter] => serials to splitter 2 ) )
I had an epiphany when try to handle NON-ASSOCIATIVE array forms in my controller. This little one liner can pretty much edit ANY kind of non-associative array. For example this one just returns an array of values inputed by a new user. The $data value is the the json_decoded() value of a register form. Here is used str_replace, you could definitely do a number of things like preg matches and other things. $readyToProcessForUser = array_combine(str_replace("new_user_", "", array_keys($data)), $data); You could also do the same for the values. $readyToProcessForUser = array_combine(array_keys($data), str_replace("-", "", $data)); Or BOTH! Use full if you don't want to walk an entire array and the keys through the same callback. $readyToProcessForUser = array_combine(array_walk('trim', array_keys($data)), array_walk('custom_callback', array_values($data)));
$item = array(); array_map( function($element) use($column_name,$key,&$item){ $item[$element[$key]] = $element[$column_name]; }, $data );
This is the function for PHP4 : <?php function array_combine($arr1,$arr2) { $out = array(); foreach($arr1 as $key1 => $value1) { $out[$value1] = $arr2[$key1]; } return $out } ?>
I was looking for a function that could combine an array to multiple one, for my MySQL GROUP_CONCAT() query, so I made this function. <?php function array_combine_array(array $keys) { $arrays = func_get_args(); $keys = array_shift($arrays); /* Checking if arrays are on the same model (array('INDEX'=> array()) or array()) */ $check = count(array_unique(array_map('is_array',array_map('current',$arrays)))) === 1; if (!$check) { trigger_error('Function array_combine_array() expects all parameters to be same type array or array of array',E_USER_NOTICE); return array(); } /* Checking the model of arrays, array('INDEX' => array()) or Array() */ $assocArray = is_array(array_shift(array_map('current',$arrays))); /* If empty $Keys is given, we fill an empty array */ if (empty($keys)) $keys = array_keys(array_fill(0,max(($assocArray) ? array_map('count',array_map('current',$arrays)) : array_map('count',$arrays)),'foo')); /* Init */ $ret=array();$i=0; /* Cycling on each keys values, making an offset for each */ foreach($keys as $v) { /* Cycling on arrays */ foreach ($arrays as $k) { if ($assocArray) { /* Getting the index of the element */ $key = key($k); /* If the offset exists, we place it */ $ret[$v][$key] = isset($k[$key][$i]) ? $k[$key][$i]:false; } /* Making the array with auto-made index */ else $ret[$v][] = isset($k[$i]) ? $k[$i]: false; } /* Getting the next offset */ $i++; } return $ret; } /* Examples */ $r = array(1,2,4,10); $a1 = array('one','two','four','ten'); $a2 = array('un','deux','quatre','dix'); $a3 = array('uno','dos','quatro','diez'); print_r(array_combine_array($r,array('english' => $a1),array('french' => $a2),array('spanish' => $a3))); /* Associative index, associative subarray indexes */ print_r(array_combine_array($r,$a1,array('french' => $a2),array('spanish' => $a3))); /* Ouputs Error */ print_r(array_combine_array($r,$a1,$a2,$a3)); /* Associative index, auto-made subarray indexes */ print_r(array_combine_array(array(),array('english' => $a1),array('french' => $a2),array('spanish' => $a3))); /* Auto-made index, associative subarray indexes */ ?>
Some tips for merging same values in an array <?php $array1 = array(1,2,3,4,5,6,7,8,9,10,11,12); $array2 = array(1,2,3,13); $merged = array_merge($array1,$array2); // output normal array_merge echo '<pre>After array_merge : '; print_r($merged); echo '</pre>'; // do double flip for merging values in an array $merged = array_flip($merged); $merged = array_flip($merged); // Output after echo '<pre>After Double Flip : '; print_r($merged); echo '</pre>'; ?> Output :: After array_merge : Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 [9] => 10 [10] => 11 [11] => 12 [12] => 1 [13] => 2 [14] => 3 [15] => 13 ) After Double Flip : Array ( [12] => 1 [13] => 2 [14] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 [9] => 10 [10] => 11 [11] => 12 [15] => 13 )
Khaly's PHP4 code below does not work correctly in all cases. Consider when your array consists of floats: <?php $okay = array(0, 10, 20, 30); $not_okay = array(0, 0.5, 1, 1.5); $foo = array_combine($okay, $okay); $bar = array_combine($not_okay, $not_okay); /* Results: $foo = { [0]=> int(0) [10]=> int(10) [20]=> int(20) [30]=> int(30) } $bar = { [0]=> float(0.5) [1]=> float(1.5) } */ ?> What can you do? In my case, I was just zipping up some select-box options, so I converted everything in my floats to strings.
Function eliminates the error Throws E_WARNING if the number of elements in keys and values does not match. function arrCombine($arr1 = array(),$arr2 = array()){ if(is_array($arr1) && is_array($arr2)): $cntArr1 = count($arr1); $cntArr2 = count($arr2); $difference = max($cntArr1,$cntArr2) - min($cntArr1,$cntArr2); if($cntArr1 > $cntArr2): for ($i=1;$i<=$difference;$i++){ $arr2[$cntArr2+$i] = $cntArr2 + 1; } return array_combine($arr1,$arr2); elseif($cntArr1 < $cntArr2): for ($i=1;$i<=$difference;$i++){ $arr1[$cntArr1+$i] = count($arr1) + 1; } return array_combine($arr1,$arr2); else: return array_combine($arr1,$arr2); endif; endif; } $array = [1,4,5,6,7,8]; $array2 = ['john','smith']; var_dump( arrCombine($array,$array2 )); array (size=6) 1 => string 'john' (length=4) 4 => string 'smith' (length=5) 5 => int 3 6 => int 3 7 => int 3 8 => int 3 var_dump( arrCombine($array2,$array) ); array (size=6) 'john' => int 1 'smith' => int 4 3 => int 5 4 => int 6 5 => int 7 6 => int 8
You can create an array hashset from a flat array, storing both keys and values, with array_combine(). This works with duplicate values in the array too. <?php $flat_array = array( 'one', 'two', 'three', 'three', 'four', 'one' ); $set = array_combine($flat_array, $flat_array); var_dump($set); ?> This outputs the following: array(4) { ["one"]=> string(3) "one" ["two"]=> string(3) "two" ["three"]=> string(5) "three" ["four"]=> string(4) "four" }
<?php /** * Return alternatives defined by values of each parameters. * * Exemple : * * array_alternatives(array('foo','bar'), array('baz', 'qux')); * array( * array('foo', 'baz'), * array('bar', 'baz'), * array('foo', 'qux'), * array('bar', 'qux'), * ); * * array_alternatives(array('a'), array('simple-minded'), array('solution')); * array( * array('a', 'simple-minded', 'solution') * ); * * array_alternatives(array('a'), array('red', 'blue'), array('car')); * array( * array('a', 'red', 'car'), * array('a', 'blue', 'car'), * ); * * @param array $first_element * @param array $second_element * @return array * @author Xavier Barbosa */ function array_alternatives(array $first_element, array $second_element) { $lists = func_get_args(); $total_lists = func_num_args(); for($i=0; $i<$total_lists; $i++) { $list =& $lists[$i]; if (is_array($list) === FALSE) throw new Exception("Parameter $i is not an array."); if (count($list) === 0) throw new Exception("Parameter $i has no element."); unset($list); } // Initialize our alternatives $alternatives = array(); foreach($lists[0] as &$value) { array_push($alternatives, array($value)); unset($value); } unset($lists[0]); // Process alternatives for($i=1; $i<$total_lists; $i++) { $list =& $lists[$i]; $new_alternatives = array(); foreach($list as &$value) { foreach($alternatives as $_) { array_push($_, $value); array_push($new_alternatives, $_); } } // Rotate references, it's cheaper than copy array like `$alternatives = $new_alternatives;` $alternatives =& $new_alternatives; unset($new_alternatives, $list, $lists[$i]); } return $alternatives; } ?>
This may be obvious, but I don't see anything about it on the manual page, so a friendly warning... The array you are using as keys must have all unique values. If not, array elements get dropped. <?php $arr_notUnique = array('one' , 'one' , 'two'); $arr_b = array('red' , 'green' , 'blue'); $arr_combo = array_combine($arr_notUnique, $arr_b); ?> Results: Array ( [one] => green [two] => blue ) NOT: Array ( [one] => red [one] => green [two] => blue )
array_combine() returns NULL instrad of FALSE, when non-array parameters are given (issuing warning). <?php //NULL var_dump(array_combine('string',array(42))); ?>