array_uintersect 将多维数组的每一行中的特定元素与字符串的平面数组进行比较

Posted

技术标签:

【中文标题】array_uintersect 将多维数组的每一行中的特定元素与字符串的平面数组进行比较【英文标题】:array_uintersect comparing specific element in each row of a multidimensional array against a flat array of strings 【发布时间】:2022-01-24 00:42:29 【问题描述】:

是否可以使用array_uintersect() 将字符串与更深一层(在数组中)的字符串进行比较?还是会进行一些排序,并且在将这些参数提供给值比较函数(回调)时在幕后交换这些参数?

目的是从 $urls 中删除重复项。

$urls:Array
(
    [0] => Array
        (
            [url] => https://www.example.com/
            [parent_url] => https://www.example.com/bleh/bleh.aspx
        )

    [1] => Array
        (
            [url] => https://www.example.com/
            [parent_url] => https://www.example.com/bla/bla.aspx
        )
)

$urls_uniq: Array
(
    [1] => https://www.example.com/
    [2] => https://www.example.com/go/173.aspx
)

function compareDeepValue($val1, $val2)

   if (is_array($val1) && empty($val1))
    return 0;
   

   // here I assume val1 is always an array (elements
   // from $urls) and val2 is always a string (elements from urls_uniq)
   return strcmp($val1['url'], $val2);  


$intersect = array_uintersect($urls, $urls_uniq, 'compareDeepValue');

它在回调函数中给了我这个错误(交换变量没有帮助):

strcmp(): 参数 #1 ($string1) 必须是字符串类型,给定数组

【问题讨论】:

【参考方案1】:

strcmp 函数需要字符串参数进行比较。

是否需要删除来自$urls_uniq$urls 中的url 的所有实例,还是应该只删除1 个实例而不考虑parent_url

如果array_uintersect 是绝对必要的,我会尝试=== 比较而不是strcmp

【讨论】:

我知道 strcmp 需要字符串,因此我使用了 ['url'] 构造(数组中的字符串)。应保留 $urls 中的唯一 url(不管 parent_url)。【参考方案2】:

作为优化,array_uintersect() 实际上是在做一些排序,这就是为什么它期望三路比较返回值(-101)。这意味着您不能假设提供给回调函数的第一个参数将始终是第一个数组中的值,而第二个参数是第二个数组中的值。这也意味着you should not simply return 0 on qualifying outcomes and 1 on disqualifying outcomes。

在下面的 sn-p 中,您会看到我在尝试访问变量的 ['url'] 元素时正在合并 null。对于不是数组或没有url 键的变量,将使用变量本身——这适用于您的示例数据。为了稳定性,请使用提供 3 路返回值的技术。

代码:(Demo)

$urls = [
    ['url' => 'https://www.example.com/', 'parent_url' => 'https://www.example.com/bleh/bleh.aspx'],
    ['url' => 'https://www.example2.com/', 'parent_url' => 'https://www.example2.com/blar.aspx'],
    'not an array',
    ['url' => 'https://www.example.com/', 'parent_url' => 'https://www.example.com/bla/bla.aspx'],
];

$urls_uniq = ['https://www.example.com/', 'https://www.example.com/go/173.aspx'];

var_export(
    array_uintersect(
        $urls,
        $urls_uniq,
        function($a, $b) 
            // echo json_encode($a) . ' VS ' . json_encode($b) . "\n"; // uncomment to see what's happening
            // return ($a['url'] ?? null) === $b ? 0 : 1;  // this doesn't work.
            // return ($a['url'] ?? $a) === ($b['url'] ?? $b) ? 0 : 1;  // this doesn't work
            return strcmp($a['url'] ?? $a, $b['url'] ?? $b);
            // or return ($a['url'] ?? $a) <=> ($b['url'] ?? $b);
        
    )
);

输出:

array (
  0 => 
  array (
    'url' => 'https://www.example.com/',
    'parent_url' => 'https://www.example.com/bleh/bleh.aspx',
  ),
  3 => 
  array (
    'url' => 'https://www.example.com/',
    'parent_url' => 'https://www.example.com/bla/bla.aspx',
  ),
)

【讨论】:

以上是关于array_uintersect 将多维数组的每一行中的特定元素与字符串的平面数组进行比较的主要内容,如果未能解决你的问题,请参考以下文章

js中多维数组转一维

使用了无效的操作数类型:array_uintersect 需要数组

将多个数组的每一项平均到一个数组中

js 将数组中的每一项安装奇偶重新组合成一个数组对象

PHP:array_uintersect()意外的输入参数[重复]

数组高级