[英]Filter & sort multidimensional array with multiple values
我有一个大的多维数组,如下所示:
Array(
[1] => Array ( [type] => blah1 [category] => cat1 [exp_range] => this_week )
[2] => Array ( [type] => blah1 [category] => cat2 [exp_range] => next week )
[3] => Array ( [type] => blah1 [category] => cat1 [exp_range] => next week )
[4] => Array ( [type] => blah2 [category] => cat2 [exp_range] => this_week )
)
我希望能够使用多个过滤器过滤此数组。
例如。 在类别= cat1和类型= blah1的情况下进行过滤将返回数组1和3。
我有以下函数将返回键1,2,3这是不正确的,因为数组2没有cat1和blah1
谁能看到我需要做些什么才能使它工作?
如果可以的话,还可以将sortin合并到此函数中吗?
function array_searcher($needles, $array) {
foreach ($needles as $needle) {
foreach ($array as $key => $value) {
foreach ($value as $v) {
if ($v == $needle) {
$keys[] = $key;
}
}
}
}
return $keys;
}
我决定重写我的答案,以适应过滤和排序。 我采用了一种面向对象的方法来解决此问题,下面将详细介绍。
您可以在此ideone.com现场演示中查看所有此代码的实际操作。
我做的第一件事是定义两个接口。
interface Filter {
public function filter($item);
}
interface Comparator {
public function compare($a, $b);
}
顾名思义,“ Filter
用于过滤,“ Comparator
器”用于比较。
接下来,我定义了三个实现这些接口的具体类 ,并完成了我想要的。
首先是KeyComparator
。 该类只是将一个元素的键与另一个元素的键进行比较。
class KeyComparator implements Comparator {
protected $direction;
protected $transform;
protected $key;
public function __construct($key, $direction = SortDirection::Ascending, $transform = null) {
$this->key = $key;
$this->direction = $direction;
$this->transform = $transform;
}
public function compare($a, $b) {
$a = $a[$this->key];
$b = $b[$this->key];
if ($this->transform) {
$a = $this->transform($a);
$b = $this->transform($b);
}
return $a === $b ? 0 : (($a > $b ? 1 : -1) * $this->direction);
}
}
您可以指定排序方向,以及在比较之前对每个元素执行的转换。 我定义了一个帮助类来封装我的SortDirection
值。
class SortDirection {
const Ascending = 1;
const Descending = -1;
}
接下来,我定义了MultipleKeyComparator
,它接受多个KeyComparator
实例,并使用它们将两个数组相互比较。 它们被添加到MultipleKeyComparator
的顺序是优先顺序。
class MultipleKeyComparator implements Comparator {
protected $keys;
public function __construct($keys) {
$this->keys = $keys;
}
public function compare($a, $b) {
$result = 0;
foreach ($this->keys as $comparator) {
if ($comparator instanceof KeyComparator) {
$result = $comparator->compare($a, $b);
if ($result !== 0) return $result;
}
}
return $result;
}
}
最后,我创建了MultipleKeyValueFilter
,它意味着根据键/值对数组过滤数组:
class MultipleKeyValueFilter implements Filter {
protected $kvPairs;
public function __construct($kvPairs) {
$this->kvPairs = $kvPairs;
}
public function filter($item) {
$result = true;
foreach ($this->kvPairs as $key => $value) {
if ($item[$key] !== $value)
$result &= false;
}
return $result;
}
}
现在,给定输入数组( 注意我重新排列它们以使排序明显 ):
$array = array (
'1' => array ('type' => 'blah2', 'category' => 'cat2', 'exp_range' => 'this_week' ),
'2' => array ('type' => 'blah1', 'category' => 'cat1', 'exp_range' => 'this_week' ),
'3' => array ('type' => 'blah1', 'category' => 'cat2', 'exp_range' => 'next_week' ),
'4' => array ('type' => 'blah1', 'category' => 'cat1', 'exp_range' => 'next_week' )
);
可以通过执行以下操作来实现排序:
$comparator = new MultipleKeyComparator(array(
new KeyComparator('type'),
new KeyComparator('exp_range')
));
usort($array, array($comparator, 'compare'));
echo "Sorted by multiple fields\n";
print_r($array);
可以通过执行以下操作来实现过滤:
$filter = new MultipleKeyValueFilter(array(
'type' => 'blah1'
));
echo "Filtered by multiple fields\n";
print_r(array_filter($array, array($filter, 'filter')));
在这一点上,我给了你很多代码。 我建议您的下一步是将这两部分合并为一个类。 然后,这个单一类将同时应用过滤和排序。
这样做:
$arr = array(
1 => array ( "type" => "blah1", "category" => "cat1", "exp_range" => "this_week" ),
2 => array ( "type" => "blah1", "category" => "cat2", "exp_range" => "next week" ),
3 => array ( "type" => "blah1", "category" => "cat1", "exp_range" => "this_week" ),
4 => array ( "type" => "blah2", "category" => "cat2","exp_range" => "next week" ),
);
function filter(array $arr,array $params){
$out = array();
foreach($arr as $key=>$item){
$diff = array_diff_assoc($item,$params);
if (count($diff)==1) // if count diff == 1 - Ok
$out[$key] = $item;
}
return $out;
}
$out = filter($arr,array("type" => "blah1", "category" => "cat1"));
echo '<pre>';
print_r($out);
echo '</pre>';
// output
Array
(
[1] => Array
(
[type] => blah1
[category] => cat1
[exp_range] => this_week
)
[3] => Array
(
[type] => blah1
[category] => cat1
[exp_range] => this_week
)
)
问题在于您的函数将返回包含“ cat1”或“ blah1”的每个数组的键。 您可以使用array_unique()修复它:
function array_searcher($needles, $array) {
foreach ($needles as $needle) {
foreach ($array as $key => $value) {
foreach ($value as $v) {
if ($v == $needle) {
$keys[] = $key;
}
}
}
}
return $keys;
}
$bigarray = array(
array('type' => 'blah1', 'category' => 'cat1', 'exp_range' => 'this_week'),
array('type' => 'blah1', 'category' => 'cat2', 'exp_range' => 'next week'),
array('type' => 'blah1', 'category' => 'cat1', 'exp_range' => 'next week'),
array('type' => 'blah2', 'category' => 'cat2', 'exp_range' => 'this_week')
);
$result = array_searcher(array('cat1','blah1'), $bigarray);
$unique_result = array_unique($result);
print_r($unique_result);
所以我们将你的基数组分配给一个变量:
$array = Array(
[1] => Array ( [type] => blah1 [category] => cat1 [exp_range] => this_week )
[2] => Array ( [type] => blah1 [category] => cat2 [exp_range] => next week )
[3] => Array ( [type] => blah1 [category] => cat1 [exp_range] => next week )
[4] => Array ( [type] => blah2 [category] => cat2 [exp_range] => this_week )
)
并让我们有一个包含我们的过滤器的数组:
$filter = array(
'type' => 'blah1'
'category' => 'cat1'
)
然后我们开始我们的过滤脚本
foreach ($array as $key => $row){
$i = 0;
foreach ($filter as $filterKey => $filterValue){
if ($row[$filterKey] != $filterValue){
$i++;
}}
if ($i == 0){
$filteredArray[] = $row;
}}
如果在针对我们的过滤器测试行之后$ i仍然等于0,我们将该行添加到过滤后的数组中
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.