使用多个值过滤和排序多维数组

Lee*_*Tee 2 php arrays sorting filtering multidimensional-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 )
)
Run Code Online (Sandbox Code Playgroud)

我希望能够使用多个过滤器过滤此数组.
例如.过滤where category = cat1和type = blah1将返回数组1和3.

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

任何人都可以看到我需要做些什么来使这个工作?

也可以在这个函数中加入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;
}
Run Code Online (Sandbox Code Playgroud)

cru*_*ush 5

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

您可以在此ideone.com现场演示中查看所有此代码的实际操作.


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

interface Filter {
    public function filter($item);
}

interface Comparator {
    public function compare($a, $b);
}
Run Code Online (Sandbox Code Playgroud)

顾名思义,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以指定排序方向,以及在比较之前对每个元素执行的转换.我定义了一个帮助类来封装我的SortDirection值.

class SortDirection {
    const Ascending = 1;
    const Descending = -1;
}
Run Code Online (Sandbox Code Playgroud)

接下来,我定义了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;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,我创建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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,给定输入数组(注意我重新排列它们以使排序明显):

$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' )
);
Run Code Online (Sandbox Code Playgroud)

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

$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);
Run Code Online (Sandbox Code Playgroud)

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

$filter = new MultipleKeyValueFilter(array(
    'type' => 'blah1'
));

echo "Filtered by multiple fields\n";
print_r(array_filter($array, array($filter, 'filter')));
Run Code Online (Sandbox Code Playgroud)

在这一点上,我给了你很多代码.我建议你的下一步是将这两个部分组合成一个单独的类.然后,这个单个类将同时应用过滤和排序.