首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有多个值的多维数组的筛选和排序

具有多个值的多维数组的筛选和排序
EN

Stack Overflow用户
提问于 2014-01-23 21:30:37
回答 5查看 5.4K关注 0票数 2

我有一个大型多维数组,如下所示:

代码语言:javascript
运行
复制
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和type = blah1将返回数组1和3。

下面的函数将返回键1,2,3,这是不正确的,因为数组2没有cat1blah1

有人能看到我需要做些什么才能让这件事奏效吗?

如果是这样的话,是否有可能将索尔丁纳入这一功能?

代码语言:javascript
运行
复制
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;
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-01-23 21:48:55

我决定重写我的答案,以适应过滤和排序。我采用了一种非常面向对象的方法来解决这个问题,我将在下面详细介绍。

您可以在这个ideone.com live demonstration上看到所有这些代码都在运行。

我做的第一件事是定义了两个接口。

代码语言:javascript
运行
复制
interface Filter {
    public function filter($item);
}

interface Comparator {
    public function compare($a, $b);
}

顾名思义,Filter用于过滤,Comparator用于比较。

接下来,我定义了三个实现这些接口的具体类,并完成了我想要的。

首先是KeyComparator。这个类简单地将一个元素的键与另一个元素的键进行比较。

代码语言:javascript
运行
复制
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);
    }
}

您可以指定一个排序方向,以及要对每个元素进行比较之前进行的转换。我定义了一个helped类来封装我的SortDirection值。

代码语言:javascript
运行
复制
class SortDirection {
    const Ascending = 1;
    const Descending = -1;
}

接下来,我定义了MultipleKeyComparator,它接受多个KeyComparator实例,并使用它们来比较两个数组。将它们添加到MultipleKeyComparator中的顺序是优先级的顺序。

代码语言:javascript
运行
复制
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,用于基于键/值对的数组过滤数组:

代码语言:javascript
运行
复制
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;
    }
}

现在,给定输入数组(注意,为了使排序变得明显,我对它们进行了一些重新排列):

代码语言:javascript
运行
复制
$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' )
);

可以通过执行以下操作来实现排序:

代码语言:javascript
运行
复制
$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);

可以通过执行以下操作来实现过滤:

代码语言:javascript
运行
复制
$filter = new MultipleKeyValueFilter(array(
    'type' => 'blah1'
));

echo "Filtered by multiple fields\n";
print_r(array_filter($array, array($filter, 'filter')));

在这一点上,我给了您大量的代码。我建议您的下一步是将这两部分合并成一个类。然后,这个单独的类将同时应用过滤和排序。

票数 5
EN

Stack Overflow用户

发布于 2014-01-23 21:53:06

做:

代码语言:javascript
运行
复制
$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
    )

)
票数 1
EN

Stack Overflow用户

发布于 2014-01-23 21:53:12

问题在于,您的函数将返回每个包含"cat1“或"blah1”的数组的键。您可以使用array_unique()修复它:

代码语言:javascript
运行
复制
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);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21319729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档