18

我习惯于 perl 的 map() 函数,其中回调可以同时分配键和值,从而创建一个关联数组,其中输入是一个平面数组。我知道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" />其中每个此类字段都以“field-”为前缀。

我们要做的是,首先,只获取那些实际上以“field-”开头的输入字段的列表,然后我们要创建一个名为的关联数组$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 并检查它是否有前缀,如果所以,将它和它的值弹出到一个数组中)

4

4 回答 4

46

几天前我遇到了完全相同的问题。使用 是不可能的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" }

于 2012-11-19T20:53:51.547 回答
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() 加上自定义插入语句强制问题更容易阅读和更优雅。

好的!

于 2013-03-08T21:29:22.593 回答
2

据我所知,在一个表达式中是完全不可能的,所以你不妨使用一个foreach循环,à la

$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;
}
于 2012-07-19T18:09:15.553 回答
1

算子的好用例yield

$arr = array('a','b','c','d');

$fct = function(array $items) {
            foreach($items as $letter)
            {
                yield sprintf("key-%s",
                    $letter
                ) => "yes";
            }
        };

$newArr = iterator_to_array($fct($arr));

这使:

array(4) {
  'key-a' =>
  string(3) "yes"
  'key-b' =>
  string(3) "yes"
  'key-c' =>
  string(3) "yes"
  'key-d' =>
  string(3) "yes"
}
于 2019-04-24T12:52:28.330 回答