php 基于子数组重复值删除数组项,然后按自定义顺序排序

eh57zj3b  于 2022-12-01  发布在  PHP
关注(0)|答案(6)|浏览(147)

删除基于重复值的数组项,这些重复值在数组中出现在更深的一层。一旦这些重复项被排序,那么重新排序新的数组将是很酷的。
这是当前输入数组...

$downloads = [
    ['type' => 'PHOTOS'],
    ['type' => 'DOCUMENTS'],
    ['type' => 'DOCUMENTS'],
    ['type' => 'VIDEOS'],
    ['type' => 'PHOTOS'],
];

我想删除此输入中的所有重复项,这样我就只剩下这个新输出了...

[
    ['type' => 'PHOTOS'],
    ['type' => 'DOCUMENTS'],
    ['type' => 'VIDEOS'],
]

但是有没有可能对每个TYPE值进行设置和排序。例如,我可以使用变量或其他东西设置预定义的顺序。有没有关于将新数组重新排序为特定顺序的建议。使用这个新顺序...

$photos = 1;
$videos = 2;
$documents = 3;

或者使用数组的新顺序。

$new_order = array(
  1 => 'PHOTOS',
  2 => 'VIDEOS',
  3 => 'DOCUMENTS'
)

我试过array_unique和array_map,但是我似乎找不到如何指定哪个子数组键来检查重复项。
这是我一直以来尝试的...

$downloads = get_field('downloads');
$types = array_unique($downloads));

以及

$downloads = get_field('downloads');
$types = array_map("unserialize", array_unique(array_map("serialize", $downloads)));

我还没来得及给数组排序呢。

vktxenjb

vktxenjb1#

使用array_columnarray_maparray_searchusort函数的解决方案:

$new_order = array(
  0 => 'PHOTOS',
  1 => 'VIDEOS',
  2 => 'DOCUMENTS'
);

// $downloads is your input array
$types = array_map(function ($v) {
    return ['TYPE' => $v];
},array_unique(array_column($downloads, 'TYPE')));

usort($types, function($a, $b) use($new_order){
    $a_key = array_search($a['TYPE'], $new_order);
    $b_key = array_search($b['TYPE'], $new_order);

    if ($a_key == $b_key) return 0;
    return ($a_key < $b_key)? -1 : 1;
});

print_r($types);

输出:

Array
(
    [0] => Array
        (
            [TYPE] => PHOTOS
        )

    [1] => Array
        (
            [TYPE] => VIDEOS
        )

    [2] => Array
        (
            [TYPE] => DOCUMENTS
        )
)
cgyqldqp

cgyqldqp2#

用于删除“子阵列”重复项的快速而又不繁琐的解决方案:

$a = [];
$a[]['type'] = 'photos';
$a[]['type'] = 'documents';
$a[]['type'] = 'documents';
$a[]['type'] = 'videos';
$a[]['type'] = 'photos';

$b = [];
foreach( $a as $index => $subA ) {
   if( in_array($subA['type'], $b) ) {
        unset($a[$index]);
   } else {
       $b[] = $subA['type'];
   }
}

关于排序:只需要按照需要的顺序设置索引,然后在删除重复项后使用ksort(假设我没有理解错)。

tquggr8v

tquggr8v3#

简单地使用array_intersect来计算两个数组的公共部分。如果你使用order array作为第一个参数,那么它的顺序将被保留。
您的输入:

$input = [
    ['TYPE' => 'PHOTOS'],
    ['TYPE' => 'DOCUMENTS'],
    ['TYPE' => 'DOCUMENTS'],
    ['TYPE' => 'VIDEOS'],
    ['TYPE' => 'PHOTOS']
];

我已经写了简单的函数来实现你的所有需求:

function do_awesomness($input, $key = 'TYPE', $order = ['PHOTOS', 'VIDEOS', 'DOCUMENTS'])
{
    $result = [];
    foreach($input as $k => $value)
        $result[] = $value[$key];
    $result = array_unique($result);

    return array_values(array_intersect($order, $result));
}

用法:

do_awesomness($input);

工作示例:http://phpio.net/s/1lo1

ux6nzvsh

ux6nzvsh4#

你可以使用array_reduce来重新实现array_unique,但是按照出现的顺序收集唯一类型。这将有助于我们稍后对数组进行排序。

$order = [
    'PHOTOS' => 1,
    'VIDEOS' => 2,
    'DOCUMENTS' => 3    
];

$types = [];
$uniqueDownloads = array_reduce(
    $downloads,
    function ($uniqueDownloads, $download) use (&$types, $order) {
        $type = $download['TYPE'];

        if (!isset($types[$type])) {
            $types[$type] = isset($order[$type]) ? $order[$type] : 0;
            $uniqueDownloads[] = $download;   
        }

        return $uniqueDownloads;
    },
    []
);

array_multisort($types, $uniqueDownloads);

遍历数组,检查类型键是否存在于$types中,如果存在,跳过此元素,否则,设置此键并从$order中赋值给它(这将用于排序)。
然后我们使用array_multisort通过排序$types来排序$uniqueDownloads
这是working demo
阅读更多关于anonymous functions的信息。我已经通过引用&传递了$types,所以函数改变了原始数组的值,但没有改变副本的值。

xzv2uavs

xzv2uavs5#

对于自定义订购,我推荐usort

$array = [
    ['TYPE'=>'PHOTOS'],
    ['TYPE'=>'DOCUMENTS'],
    ['TYPE'=>'VIDEOS']
    ];

function customOrder($a, $b){
    $newOrder = [
      'PHOTOS' => 1,
      'VIDEOS' => 2,
      'DOCUMENTS' => 3
    ];

    $valA = (array_key_exists($a['TYPE'],$newOrder))?$newOrder[$a['TYPE']]:999;
    $valB = (array_key_exists($b['TYPE'],$newOrder))?$newOrder[$b['TYPE']]:999;

    if($valA > $valB){
        $result = 1;
    } elseif($valA < $valB){
        $result = -1;
    } else {
        $result = 0;
    }
    return $result;
}

usort($array, "customOrder");
var_dump($array);
w8biq8rn

w8biq8rn6#

因为排序数组似乎是可能下载值的详尽列表,所以可以只按下载值过滤该静态数组。
代码:(Demo

var_export(
    array_intersect(
        $new_order,
        array_column($downloads, 'type')
    )
);

如果下载数组中可能存在排序数组中未表示的值,则应调整问题中的样本数据,以更好地表示应用程序数据。

相关问题