【问题标题】:Remove array items based on sub array duplicate values and then re-order array根据子数组重复值删除数组项,然后重新排序数组
【发布时间】:2016-12-04 07:19:21
【问题描述】:

删除基于重复值的数组项,这些重复值出现在数组内部更深 1 级。一旦对重复项进行排序,那么重新排序新数组会很酷。

这是当前的输入数组...

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

  [1] => ARRAY
    (
      [TYPE] => DOCUMENTS
    )

  [2] => ARRAY
    (
      [TYPE] => DOCUMENTS 
    )

  [3] => ARRAY
    (
      [TYPE] => VIDEOS
    )

  [4] => ARRAY
    (
      [TYPE] => PHOTOS
    )

)

如果我从这个数组中输出TYPE,我会得到这个......

[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)));

我还没有重新排序数组。

谢谢

【问题讨论】:

  • 我不确定您所说的重新排序技术是什么。但您可以使用array_unique 删除这些重复项。
  • array_unique 不适用于多维数组
  • 请你把一些东西清理一下。你想只获取唯一类型的数组还是具有唯一类型的输入项数组?

标签: php arrays duplicates


【解决方案1】:

使用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
        )
)

【讨论】:

  • 我刚刚在phpio.net/s/1lql 进行了测试,效果也很好。谢谢你的时间。那么您认为哪个更快,your answerpiotr's answer。 @piotr 的答案比你的代码少。
  • @joshmoto,你忘了一件事 - 在@piotr 的回答中,结果数组没有 TYPE 键,因为它们出现在初始数组中
【解决方案2】:

删除“子数组”重复项的快速而肮脏的解决方案:

$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(假设我确实理解您的意思)。

【讨论】:

  • 可能又快又脏,但它可以很好地删除所有重复项 :-) phpio.net/s/1lpi 谢谢你的时间,但我想把它交给@piotr 因为他的功能是我所追求的。不过谢谢
【解决方案3】:

只需使用计算两个数组的公共部分的array_intersect。如果您使用 order 数组作为第一个参数,则将保留其顺序。

您的意见:

$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

【讨论】:

  • 这对我来说确实很棒,但我在 phpio.nets 上玩了一个我正在尝试过滤的实际数组,它引发了一个错误。是因为您的示例数组只有一层深吗?请查看使用我的多维数组输入 phpio.net/s/1lpl 修改的工作示例
  • 一切正常。只需将TYPE 更改为type,并将值排序为PhotosVideosDocuments
  • 这只会返回唯一类型的数组,而不是唯一输入项的数组。此外,您可以删除foreach 并使用array_column
  • 没有。 @joshmoto 想要返回 TYPE 索引。我的函数允许他返回任何其他索引。
  • 其实你是对的,我刚刚在phpio.net/s/1lpr 更新了区分大小写的值,它给了我完美的输出。感谢@piotr 为您提供解决方案
【解决方案4】:

您可以使用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 引用&amp; 传递了&amp;,所以函数改变了原始数组的值,而不是副本的值。

【讨论】:

  • 感谢您的帮助,尽管另一个人回答了并且他使用的数组与我认为的数组不同。虽然我可能是错的,但我现在将在我的现场环境中使用这两种解决方案进行测试。但是我已经用我的数组输入更新了你的工作演示。 sandbox.onlinephpfunctions.com/code/… 谢谢
  • @joshmoto,TYPEtype 键的问题。您可以更改大小写,它会起作用。
  • 我玩过你的版本.. 参见小提琴phpio.net/s/1lq5,基于我在其他答案中使用的相同数组,我确定这可能是一个错误我'已经做了,但我可能会把问题交给@piotr,他的功能可以满足我的需要。感谢您的宝贵时间。
  • @joshmoto,在小提琴中,添加 var_dump($uniqueDownloads); 以查看输出是有意义的。
【解决方案5】:

对于定制订购,我推荐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);

【讨论】:

  • 感谢您抽出宝贵时间,我已经将@piotr 的答案标记为最佳答案,但我也正在测试您的答案..
  • 我在这里测试了你的代码,但它似乎输出了我所有的数组输入...phpio.net/s/1lqf 但别担心,我现在有了一个工作函数。非常感谢
  • 这是唯一的自定义订购功能。就个人而言,最好的答案是@RomanPerekhrest 的代码。
  • 啊,我明白了,谢谢。那么为什么 [@RomanPerekhrest's](phpio.net/s/1lql) 代码比 @piotr's code 更好?它们都很好用,我很困惑为什么哪个更好..?
猜你喜欢
  • 1970-01-01
  • 2020-11-06
  • 2020-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 2013-11-01
相关资源
最近更新 更多