过滤数组以保留值字符串中存在键的元素

Filter array to keep elements where the key exists in the value string

我需要通过检查是否在其值中找到其键(区分大小写)作为子字符串来过滤我的平面关联字符串类型值数组。换句话说,如果元素的键在元素的值中,我想保留输出数组中的元素。

我可以通过调用 strpos() 来制作经典的 foreach() 循环,但这感觉很乏味。还有更多 modern/elegant 方法吗?

我的代码:

$array = [
    'needle' => 'needle in haystack text',
    'Need' => 'another needle',
    'fine' => 'refined',
    'found' => 'Foundation',
    '' => 'non-empty haystack',
    'missing' => 'not here',
    'This is 0 in a haystack!',
];

$result = [];
foreach ($array as $needle => $haystack) {
    if (strpos($haystack, $needle) !== false) {
        $result[$needle] = $haystack;
    }
}
var_export($result);

输出:

array (
  'needle' => 'needle in haystack text',
  'fine' => 'refined',
  '' => 'non-empty haystack',
  0 => 'This is 0 in a haystack!',
)

从PHP5.6开始,array_filter()获得了ARRAY_FILTER_USE_BOTH旗帜。这使得 array_filter() 成为等效的 functional-style 技术。

代码:(Demo)

var_export(
    array_filter(
        $array,
        function($haystack, $needle) {
            return strpos($haystack, $needle) !== false;
        },
        ARRAY_FILTER_USE_BOTH
    )
);

这样做的一个好处是 $result 不需要声明。另一方面,尽管它在技术上可以写成 one-liner,但它会产生很长的代码行——根据 [,这会使代码接近或超过每行的软字符限制 PSR-12 coding standards。所以到目前为止,几乎没有什么可以迫使您更改代码。

好消息是 PHP8 专门引入了 str_contains() 来提供一个干净、原生的 case-sensitive 函数来替换 strpos() 及其强制性严格布尔值 false 检查。

代码:(Demo)

var_export(
    array_filter($array, 'str_contains', ARRAY_FILTER_USE_BOTH)
);

此 returns 与所需的输出相同,是 functional-style、one-liner,并且仅包含 59 个字符。我会推荐这种方法。

为了理解发生了什么,使用 array_filter() 的详细语法,其中 str_contains() 不是由其字符串名称调用的,如下所示:

var_export(
    array_filter(
        $array,
        fn($haystack, $needle) => str_contains($haystack, $needle),
        ARRAY_FILTER_USE_BOTH
    )
);