这是数据
$array = array(
'random' => 1,
'pewpew' => 2,
'temp' => 5,
'xoxo' => 3,
'qweqweqe' => 4,
);
$fields = array('random', 'xoxo', 'temp');
我需要得到结果:
$result = array(
'random' => 1,
'xoxo' => 3,
'temp' => 5,
);
我的意思是来自$ fields的密钥存在/订单适用于$ array。
问题是: 我可以仅使用array_函数执行此转换吗? (我不想使用迭代) 如果是:你能链接我需要的功能吗?
(对不起拼写错误)
UPD。
PHP 5.2
答案 0 :(得分:5)
$result=array_intersect_key($array ,array_flip($fields) );
答案 1 :(得分:3)
// little trick required here...
$fields = array('random' => 0, 'xoxo' => 0, 'temp' => 0);
$result = array_intersect_key($array,$fields);
答案 2 :(得分:2)
我一直对这些类型的问题感兴趣,其中包括 高效代码 (在代码使用和速度方面)。也就是说,我试过并基准几种不同的方法,没有什么是有效的和简单的foreach
!
我尝试了所有发布的解决方案,以及我自己的array_walk和基本的foreach。我运行了几个测试,包括Miraage发布的数组和字段,还有一些包含更大的数组。我还注意到结果有些奇怪,例如,如果$ fields的值不在$ array中,则为其他值。
我已经快速订购了。
$result = array();
foreach ($fields as $k)
{
if (isset($array[$k]))
$result[$k] = $array[$k];
}
$result = array_diff_key($fields, $array);
function array_filter_by_key($array, $fields)
{
$result = array();
foreach ($fields as $k)
{
if (isset($array[$k]))
$result[$k] = $array[$k];
}
return $result;
}
function array_walk_filter_by_key($item, $key, $vars)
{
if (isset($vars[1][$item]))
$vars[0][$item] = $vars[1][$item];
}
$result = array();
array_walk($fields, 'array_walk_filter_by_key', array(&$result, &$array));
$result = array();
reset($fields);
while (list($key, $value) = each($fields))
{
if (isset($array[$value]))
$result[$value] = $array[$value];
}
$result = array_intersect_key($array, array_flip($fields));
$result = array_replace(
array_fill_keys($fields, false),
array_intersect_key($array, array_flip($fields))
);
$flip = array_flip($fields);
$result = array_replace(
array_intersect_key($flip, $array),
array_intersect_key($array, $flip)
);
function array_walk_filter_by_key_null(&$item, $key, $array)
{
if (isset($array[$key]))
$item = $array[$key];
else
$item = null;
}
$result = array_flip($fields);
array_walk($result, 'array_walk_filter_by_key_null', $array);
$flip = array_flip($fields);
$result = array_intersect_key(
array_replace($flip, $array),
array_intersect_key($flip, $array)
);
$result = array_splice(
array_merge(array_flip($fields), $array),
0,
count($fields)
);
就是这样。 DIY不能打败。有时人们认为内置函数更快,但情况并非总是如此。编程器现在相当不错。
答案 3 :(得分:1)
我相信这可以按照您的要求运作。
$result = array_splice(array_merge(array_flip($fields) , $array) , 0 , count($fields));
答案 4 :(得分:1)
只是为了解决难题:
$result = array_replace(
array_intersect_key(array_flip($fields), $array),
array_intersect_key($array, array_flip($fields))
);
第一个array_intersect以良好的顺序创建字段列表,另一个使用array_replace功能来创建第一个数组中不存在的键。
满足您的要求。但我不会在任何生产代码中使用它,因为这可能相当沉重(虽然我没有基准测试,所以这只是一种直觉)。 array_walk解决方案似乎更轻松。
答案 5 :(得分:1)
此代码保留顺序并根据需要在PHP 5.2中运行
一行:
$result = array_merge( array_flip($fields),
array_intersect_key(
$array,
array_flip( $fields )
)
);
表现:
$flip = array_flip($fields);
$result = array_merge( $flip
array_intersect_key(
$array,
$flip
)
);
答案 6 :(得分:0)
如果您想保留$fields
的密钥订单,可以尝试:(如果$array
中不存在密钥,则该密钥的值将为空。)
$result = array_flip($fields);
array_walk($result, function(&$item, $key, $array) {
$item = isset($array[$key]) ? $array[$key] : null;
}, $array);
var_dump($result);
答案 7 :(得分:0)
我会考虑你不能改变输入($ array或$ fields)。
如果您的数组使用$ fields中的值作为键,则可以实现此目的。之后,您可以合并两个(将$ fields作为第一个参数)并删除多余的元素。
考虑到您无法更改$ fields,我将创建它:
$tmp = array_combine($fields, range(1, count($fields)));
$result = array_merge($tmp, $array);
$result = array_splice($result, 0, count($fields));
可以在此处找到完整的工作样本(带有一些注释):http://codepad.org/H0CDN7ok
答案 8 :(得分:0)
我的尝试:
array_replace(
array_fill_keys($fields, false),
array_intersect_key($array, # Keys in array, without order
array_flip($fields))));
按照与$ array相同的顺序获取密钥很容易。然后为了让它们按正确顺序排列,我构建了一个数组,其中的键等于$ fields。 Array_replace完成了其余的工作。
解决方案是“稳定的”,因为$ array中缺少的键将被替换为FALSE,因此可以在需要时被过滤掉。
array_flip遍历大小为N的字段数组,array_intersect遍历N个大小的数组,array_fill_keys为N,最后的array_replace是,我相信N ^ 2.
所以总费用是M * N ^ 5.
走最小的数组并从大数组中选取值是O(M ^ 2 * N ^ 2),因此对于大的N值,我怀疑PHP解决方案可能证明更快。这不会输入不在数据数组中的键。
$answer = array();
foreach($fields as $fld) // N-sized cycle
if (isset($array[$fld])) // Cost M
$answer[$fld] = // Assignment is N*1/2
$array[$fld]; // Getting value is another M
(稍后会有一些困惑)
我跑了一张支票,我想我一定是犯了一些愚蠢的错误,因为我得到的时间完全是荒谬的。不可否认,我使用的是一个非常短的$ fields数组,所以我预计结果会有偏差,但不会这个偏斜。除非使用一些非常聪明的哈希技巧计算$ answer [$ fld],否则解释解的真实成本不是O(M ^ 2 * N ^ 2),而是O(K * N ^ 2),其中K小。< / p>
如果有人想和我一起玩或告诉我我可能犯了什么愚蠢的错误,这就是基准。
关于发布这个问题,我有两种想法,因为另一个明显的解释是,我在某个地方犯了一个荒谬,愚蠢的错误,我最终会在我脸上染上鸡蛋,但是,哦,到底是怎么回事。 / p>
$array = array(
'random' => 1,
'pewpew' => 2,
'temp' => 5,
'xoxo' => 3,
'qweqweqe' => 4,
);
$fields = array('random', 'xoxo', 'temp');
// Let's not print anything just yet, maybe that's what screwing the timer?
$results = '';
$duh = 0;
for ($cycle = 0; $cycle < 10; $cycle++)
{
// Add some more elements to $array.
for ($i = 0; $i < 10000; $i++)
{
$k = uniqid();
$array[$k] = 42;
}
$start = explode(' ', microtime());
// WTF? Do more cycles to average the timing.
for ($j = 0; $j < 10; $j++)
{
// 0 or 1 to switch
if (1)
{
// INTERPRETED ANSWER
$answer = array();
foreach($fields as $fld) // N-sized cycle
if (isset($array[$fld])) // Cost M
$answer[$fld] = // Assignment is N*1/2
$array[$fld]; // Getting value is another M
} else {
// FUNCTION ANSWER
$answer = array_replace(
array_fill_keys($fields, false),
// array_combine($fields, $fields),
array_intersect_key($array, # Keys in array, without order
array_flip($fields)));
}
// USE $answer so to avoid premature optimization?
// You can't be that clever.
$duh += strlen(serialize($answer));
}
$stop = explode(' ', microtime());
// An error in timing? Check via a stupid roundabout.
$int = $stop[1]-$start[1]+1;
$int += ($stop[0]-$start[0]);
$int -= 1;
$elapsed = number_format($int * 1000000, 2);
$results .= "".(5000*$cycle)." = $elapsed us.\n";
}
// I need to get in result:
$wanted = array(
'random' => 1,
'xoxo' => 3,
'temp' => 5,
);
// DID we get the right answer?
print "Wanted:\n"; print_r($wanted);
print "Gotten:\n"; print_r($answer);
print "Results: $results\n$duh -- count of array is " . count($array);
// And yet I have always the same realtime, name of a dog, how can that be?
// I must be doing something REALLY REALLY wrong somewhere.
答案 9 :(得分:0)
此解决方案还处理$fields
中某些$array
不作为键出现的情况:
$flip = array_flip($fields);
$result = array_intersect_key(array_replace($flip, $array), array_intersect_key($flip, $array));
如果已知$fields
中的所有$array
都作为$flip = array_flip($fields);
$result = array_intersect_key(array_replace($flip, $array), $flip);
中的键出现,则可以使用这个更简单的解决方案:
$result = array_intersect_key(array_replace($flip=array_flip($fields), $array), $flip);
可以写成这样的单行:
$fields
如果某些$array
不是$array
的键,但0
包含计数,那么返回错误键的flip()
计数是有意义的,我们可以替换array_fill_keys($fields, 0)
与$result = array_intersect_key(array_replace($fill=array_fill_keys($fields, 0), $array), $fill);
:
array_filter()
如果需要,我们可以应用0
再次过滤掉0
。通过将false
替换为null
或$array
,当值不是计数时,我们可以标记并处理$array
中缺少密钥。
令人遗憾的是,这些解决方案与此页面上的所有其他解决方案一样,必须处理$fields
的所有键,而任何显式循环都在count($array)
上。目前看来,当count($fields)
远大于array_walk()
时,没有基于数组函数的解决方案和显式循环一样快(因为它们会在回调函数中显式构造结果,我认为array_reduce()
和array_
在这里是显式循环。
问题在于,没有任何可用的$fields
函数会破坏键和值之间的关联,因为我们想循环$array
,或者更确切地说是一个翻转的数组,也是为了保存它排序顺序,同时保持{{1}}的值,我们运气不好。
答案 10 :(得分:0)
PHP函数名为array_diff_key。
示例代码:
$array = array(
'random' => 1,
'pewpew' => 2,
'temp' => 5,
'xoxo' => 3,
'qweqweqe' => 4
);
$fields = array('random', 'xoxo', 'temp');
$result = array_diff_key($fields, $array);
这将产生所需的结果。
演示:http://shaquin.tk/experiments/array1.php
编辑:如果$fields
可以包含$array
中不是键的值,请使用以下代码:
$result = array_diff_key($fields, $array);
$result = array_intersect_key(array_flip($fields), $array);
$result = array_flip(array_diff(array_keys($result), $array));
$result = array_replace($result, $array);
$result = array_flip(array_intersect(array_flip($result), $fields));
有可能对此进行优化,但它有效!
注意:我无法链接到示例,因为我的(托管)网站没有&gt; = PHP 5.3,但是,我可以链接到类似的:http://shaquin.tk/experiments/array2.php。
答案 11 :(得分:0)
简单方法:
$array = array(
'random' => 1,
'pewpew' => 2,
'temp' => 5,
'xoxo' => 3,
'qweqweqe' => 4,
);
$fields = array('random', 'xoxo', 'temp');
$output = array();
foreach ($fields as $value)
if(isset($array[$value]))
$output[$value]=$array[$value];
答案 12 :(得分:-1)
尝试:
$result=array();
reset($fields);
while(list($key,$value)=each($fields))
{
if(isset($array[$value])) $result[$value]=$array[$value];
}
答案 13 :(得分:-1)
这将有效并保留您的订单:
$fields = array_flip($fields);
array_merge($fields,array_intersect_key($array, $fields));
$fields = array_keys($fields);
注意,你可以两次调用array_flip,但上面看起来有点“干净”。