问答中心分类: PHPPHP的array_映射,包括键
0
匿名用户 提问 4天 前

有没有这样的方法:

$test_array = array("first_key" => "first_value", 
                    "second_key" => "second_value");

var_dump(array_map(function($a, $b) { return "$a loves $b"; }, 
         array_keys($test_array), 
         array_values($test_array)));

但不是打电话array_keysarray_values,直接通过$test_array变量
所需输出为:

array(2) {
  [0]=>
  string(27) "first_key loves first_value"
  [1]=>
  string(29) "second_key loves second_value"
}
18 Answers
0
Kevin Beal 回答 4天 前

这可能是最短、最容易推理的原因:

$states = array('az' => 'Arizona', 'al' => 'Alabama');

array_map(function ($short, $long) {
    return array(
        'short' => $short,
        'long'  => $long
    );
}, array_keys($states), $states);

// produces:
array(
     array('short' => 'az', 'long' => 'Arizona'), 
     array('short' => 'al', 'long' => 'Alabama')
)
Kevin Beal 回复 4天 前

我刚刚意识到问题明确地说不要使用array_keys(). 不过,这似乎是一个愚蠢的要求。

Chinoto Vokro 回复 4天 前

该问题提供了一个使用array\u keys()的解决方案,如果提供的答案与当前解决方案相比没有任何优势(例如,调用更少的函数),那将是愚蠢的。

usoban 回复 4天 前

原始问题的答案是否定的,这是最合适的解决方案。

0
Nicholas Shanks 回答 4天 前

这是我非常简单的兼容PHP 5.5的解决方案:

function array_map_assoc(callable $f, array $a) {
    return array_column(array_map($f, array_keys($a), $a), 1, 0);
}

您提供的callable本身应该返回一个具有两个值的数组,即。return [key, value]. 内心的呼唤array_map因此生成一个数组。然后通过以下方式将其转换回一维数组:array_column.
用法

$ordinals = [
    'first' => '1st',
    'second' => '2nd',
    'third' => '3rd',
];

$func = function ($k, $v) {
    return ['new ' . $k, 'new ' . $v];
};

var_dump(array_map_assoc($func, $ordinals));

输出

array(3) {
  ["new first"]=>
  string(7) "new 1st"
  ["new second"]=>
  string(7) "new 2nd"
  ["new third"]=>
  string(7) "new 3rd"
}

部分应用
如果需要对不同的数组但相同的映射函数多次使用该函数,可以执行以下操作:部分功能应用(与’咖喱‘),这允许您仅在调用时传入数据数组:

function array_map_assoc_partial(callable $f) {
    return function (array $a) use ($f) {
        return array_column(array_map($f, array_keys($a), $a), 1, 0);
    };
}

...
$my_mapping = array_map_assoc_partial($func);
var_dump($my_mapping($ordinals));

产生相同的输出,给定$func$ordinals和之前一样。
注意:如果映射函数返回相同的键对于两个不同的输入,与后面的钥匙会赢。反转的输入数组和输出结果array_map_assoc允许较早的键获胜。(在我的示例中,返回的键不能碰撞,因为它们包含源数组的键,而源数组的键又必须是唯一的。)

可供替代的
以下是上面的一个变体,对某些人来说可能更符合逻辑,但需要PHP 5.6:

function array_map_assoc(callable $f, array $a) {
    return array_merge(...array_map($f, array_keys($a), $a));
}

在这个变体中,您提供的函数(数据数组映射在其上)应该返回一个具有一行的关联数组,即。return [key => value].array_merge. 如前所述,返回重复键将导致后面的值获胜。

n、 b.Alex83690在评论中指出array_replace在这里代替array_merge将保留整数键。array_replace不修改输入数组,因此对函数代码是安全的。

如果您使用的是PHP 5.3到5.5,那么以下内容是等效的。它使用array_reduce和二进制+数组运算符将生成的二维数组向下转换为一维数组,同时保留关键帧:

function array_map_assoc(callable $f, array $a) {
    return array_reduce(array_map($f, array_keys($a), $a), function (array $acc, array $a) {
        return $acc + $a;
    }, []);
}

用法
因此,将使用这两种变体:

$ordinals = [
    'first' => '1st',
    'second' => '2nd',
    'third' => '3rd',
];

$func = function ($k, $v) {
    return ['new ' . $k => 'new ' . $v];
};

var_dump(array_map_assoc($func, $ordinals));

注意=>而不是,在里面$func.
输出与之前相同,每个输出都可以以与之前相同的方式部分应用。

总结
原始问题的目标是使调用尽可能简单,但代价是调用更复杂的函数;特别是,能够将数据数组作为单个参数传入,而无需拆分键和值。使用本答案开头提供的功能:

$test_array = ["first_key" => "first_value",
               "second_key" => "second_value"];

$array_map_assoc = function (callable $f, array $a) {
    return array_column(array_map($f, array_keys($a), $a), 1, 0);
};

$f = function ($key, $value) {
    return [$key, $key . ' loves ' . $value];
};

var_dump(array_values($array_map_assoc($f, $test_array)));

或者,仅对于这个问题,我们可以简化为array_map_assoc()删除输出键的函数,因为问题不需要它们:

$test_array = ["first_key" => "first_value",
               "second_key" => "second_value"];

$array_map_assoc = function (callable $f, array $a) {
    return array_map($f, array_keys($a), $a);
};

$f = function ($key, $value) {
    return $key . ' loves ' . $value;
};

var_dump($array_map_assoc($f, $test_array));

所以答案是,你不能不打电话array_keys,但你可以抽象出array_keys被调用到高阶函数中,这可能已经足够好了。

icc97 回复 4天 前

array_column仅适用于PHP 5.5+,因此此答案与PHP 5.3不兼容

Erutan409 回复 4天 前

我就是那个人。PHP 5.3不再是日期的要求this答复依我拙见

Nicholas Shanks 回复 4天 前

@当然,我只是想提供一个尽可能多的答案。不过,我确实喜欢在旧系统上运行新代码。我让Netscape 1.0在一台旧Mac电脑上运行7.1系统,我偶尔用它浏览网页,只是为了让系统管理员在查看服务器日志时吓一跳:-)

Alex83690 回复 4天 前

您的第一个备选解决方案无效。您必须更换array_merge通过array_replace保留将是整数的键。

Nicholas Shanks 回复 4天 前

@Alex83690谢谢!尽管我会说“invalid”有点误导性——如果没有任何整数键(在我自己的例子中是这样的),那就好了。

Ruslan Stelmachenko 回复 4天 前

如果有人对保留键的数组映射函数感兴趣,同时它的回调可以访问键和值,并且可以只返回一个值(与普通映射函数一样),而不是“特殊格式”的值(一行关联数组),那么这里是经过稍微修改的php 5.6解决方案:function array_map_assoc(callable $f, array $a) { return array_merge(...array_map(function ($k, $v) use ($f) { return [ $k => $f($k, $v) ]; }, array_keys($a), $a)); }. 为了让它发挥作用$f必须用另一个函数包装,该函数将新值映射到[key=>new_value].

kapitan 回复 4天 前

这真是恰到好处,谢谢你,工作起来很有魅力![+1]

0
Ostap Brehin 回答 4天 前
$array = [
  'category1' => 'first category',
  'category2' => 'second category',
];
 
$new = array_map(function($key, $value) {
  return "{$key} => {$value}";
}, array_keys($array), $array);
simonhamp 回复 4天 前

这是我们都需要的整洁的解决方案

0
Tadas Sasnauskas 回答 4天 前

PHP5.3或更高版本:

$test_array = array("first_key" => "first_value", 
                    "second_key" => "second_value");

var_dump(
    array_map(
        function($key) use ($test_array) { return "$key loves ${test_array[$key]}"; },
        array_keys($test_array)
    )
);
eis 回复 4天 前

我认为要求是“而不是调用array\u键和array\u值,直接传递$test\u数组变量”,这可以在没有array\u键的情况下使用吗?

0
IanS 回答 4天 前

看这里!有一个微不足道的解决方案!

function array_map2(callable $f, array $a)
{
    return array_map($f, array_keys($a), $a);
}

如问题所述,array_map 已经完全具备所需的功能. 这里的其他答案严重地使事情过于复杂:array_walk不起作用。
用法
正如您从示例中所期望的那样:

$test_array = array("first_key" => "first_value", 
                    "second_key" => "second_value");

var_dump(array_map2(function($a, $b) { return "$a loves $b"; }, $test_array));
Brad Kent 回复 4天 前

其他答案过于复杂,因为问题具体化了qrrqy_keys()不应出于#原因使用