2012-07-19 152 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