PHP通过第二个数组对array_intersect_key()函数的结果进行排序

14

我有一个类中的方法看起来像这样;

class SomeClass {
    private $hidden = array(....);

    /**
     * @return array - numeric indexed array in order of $this->hidden.
     * Suitable for use by list(var1, var2, ...)
     */
    public function getAsList($list = array())
    {
       return array_values(array_intersect_key($this->hidden, array_flip($list) );
    }

但这并不实用,因为方法的调用者不知道实例变量$hidden中关联数组的键/值对的顺序。理想情况下,返回的数组应该与$list指定的键的顺序完全相同。例如:

$foo = new SomeClass();
list($foo, $bar, $baz) = $foo->getAsList(array('foo', 'bar', 'baz');

我可以很容易地在一个循环中编写一些明确而冗长的PHP代码来实现这个目标,但是否有一些聪明的方法可以使用各种数组函数(例如array_multisort())以最少的代码行数呈现出来(而且希望能够在编译后的代码速度上更快 —— 如果有影响,我会测试的)。

从某种意义上说,这是一个智力游戏,我还不知道答案。没有必要在不使用明确的循环的情况下完成它,但我很好奇是否可以做到。我已经花了30分钟左右的时间,但还没有找到解决方案。


1
+1 是因为我喜欢这个问题,但我也想确保你知道 extract() - goat
我知道extract()的作用。但我在我的类中使用这个方法时,明确地避免它,因为如果使用不当,它很容易引起安全问题。另外,我发现明确创建命名变量实际上比使用extract()更快,至少在我的小型基准测试中是这样的。 - CXJ
2个回答

18
也许array_replace是您难题的遗漏部分:
public function getAsList($list = array())
{
  $klist = array_flip($list);
  return array_values(array_intersect_key(array_replace($klist, $this->hidden), $klist));
}

示例 (演示):

$hidden = [
  'apples' => 19,
  'eggs' => 7,
  'grapes' => 144,
  'mushrooms' => 3,
  'oranges' => 16
];

$list = ['grapes', 'apples', 'eggs', 'oranges'];

$klist = array_flip($list);
print_r(array_values(array_intersect_key(array_replace($klist, $hidden), $klist)));

/*
Array
(
    [0] => 144
    [1] => 19
    [2] => 7
    [3] => 16
)
*/

2
这是一种情况,函数式编程在可读性、可维护性和效率方面与语言结构相比显得逊色。
我有偏向函数式编程的倾向,但在这种情况下它并不划算。
代码:(演示)
$hidden = [
  'apples' => 19,
  'eggs' => 7,
  'grapes' => 144,
  'mushrooms' => 3,
  'oranges' => 16
];

$list = ['grapes', 'apples', 'eggs', 'oranges'];
foreach ($list as $item) {
    if (isset($hidden[$item])) {
        $result[] = $hidden[$item];
    }
}

var_export($result);

输出:

array (
  0 => 144,
  1 => 19,
  2 => 7,
  3 => 16,
)

如果您坚持使用函数式编程,那么按照以下顺序执行所需操作将是最有效的:
  • 过滤数组
  • 对过滤后的数组进行键排序
  • 重新索引已排序、已过滤的数组
以下是具体操作:
代码:(演示
$flippedList = array_flip($list);
var_export(array_values(array_replace($flippedList, array_intersect_key($hidden, $flippedList))));

从逻辑上讲,对一个有多余元素的数组进行排序是没有意义的。首先需要减轻负担。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接