【问题标题】:Remove duplicates from array but ignoring one parameter从数组中删除重复项但忽略一个参数
【发布时间】:2015-06-28 05:12:18
【问题描述】:

我有一个由 PHP 对象组成的数组:

$objects[0] => $object->type => 'President'
               $object->name => 'Joe Blogs'
               $object->address => '123 Harry Street'

$objects[1] => $object->type => 'Secretary'
               $object->name => 'Joe Blogs'
               $object->address => '123 Harry Street'

$objects[2] => $object->type => 'Treasurer'
               $object->name => 'Jane Doe'
               $object->address => '456 Upton Street'

我想忽略type 参数并最终得到:

$objects[0] => $object->type => 'President'
               $object->name => 'Joe Blogs'
               $object->address => '123 Harry Street'

$objects[2] => $object->type => 'Treasurer'
               $object->name => 'Jane Doe'
               $object->address => '456 Upton Street'

我尝试了一些不同的方法,其中之一是使用foreach 循环取消设置参数type,然后尝试重置它,但我不确定如何将两个索引绑定在一起以重置他们。另一个尝试在 select 命令中使用联合,但也不能 100% 正确工作。

我只是不确定如何最好地管理type 参数。

编辑:

我试图让查询更简单一些,它现在返回一个 ID 列表,稍后我将获取地址信息。这是我想过滤掉所有重复项的新数组。

    $items['president'][0] = '1'
                       [1] = '2'
                       [2] = '3'

    $items['secretary'][0] = '1'
                       [1] = '4'
                       [2] = '5'

我想要的是

$items['president'][0] = '1'
                   [1] = '2'
                   [2] = '3'

$items['secretary'][1] = '4'
                   [2] = '5'

这样更好吗? (注意:我可以使用两种数组结构,但第二种会更好)

【问题讨论】:

  • 我尝试了一些不同的东西展示你的尝试
  • 我试图解释我的尝试,但没有任何东西接近工作,所以我不会显示我的尝试代码
  • 那么这个问题我们在哪里?
  • 我们旅途顺利,我编辑了 select 函数以使数组更好一些。这更容易吗?
  • 是的,谢谢。在处理您的答案时,我意识到第二个数组可能会让我做得更好。我很抱歉把你塞在身边。你知道第二种结构的方法吗?

标签: php arrays object multidimensional-array


【解决方案1】:

这应该适合你:

这里我只是浏览了来自$objects 的每个对象。然后,我从$unique 和array_reduce() 中检查您的所有独特对象,并检查是否有一个对象在name 和address 中具有与当前迭代相同的值。

如果$unique 中没有具有相同值name 和address 的对象,我将其添加到其中。

<?php

    $unique = [];

    foreach($objects as $o) {

        $duplicate = array_reduce($unique, function($keep, $v)use($o){
            if($v->name == $o->name && $v->address == $o->address)
                return $keep = TRUE;
        }, FALSE);

        if(!$duplicate)
            $unique[] = $o;

    }

    print_r($unique);

?>

输出:

Array
(
    [0] => stdClass Object
        (
            [type] => President
            [name] => Joe Blogs
            [address] => 123 Harry Street
        )

    [1] => stdClass Object
        (
            [type] => Treasurer
            [name] => Jane Doe
            [address] => 456 Upton Street
        )

)

编辑:

从您对新数组结构的更新问题来看,这样的事情应该可以工作:

就像在您拥有一个包含唯一值的数组以及一个用于跟踪您在 $unique 数组中已有哪些值的数组之前一样。然后你可以遍历你的数组来检查值是否已经在 values 数组中。

<?php

    $unique = [];
    $values = [];

    foreach($items as $keyOne => $arr) {

        foreach($arr as $keyTwo =>$v) {
            if(!in_array($v, $values)) {
                $unique[$keyOne][$keyTwo] = $v;
                $values[] = $v;
            }
        }
    }   

    print_r($unique);


?>

输出:

Array
(
    [president] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

    [secretary] => Array
        (
            [1] => 4
            [2] => 5
        )

)

【讨论】:

  • 非常感谢!这样做的好方法!
【解决方案2】:

你可以只使用array_unique,这个函数使用toString方法比较对象:

class obj{
    public $type;
    public $name;
    public $address;

    public function __construct($type, $name, $address){
        $this->type = $type;
        $this->name = $name;
        $this->$address = $address;
    }

    public function __toString(){
        return $this->name . $this->address;
    }
}


$objects = array(
    new obj('President','Joe Bogs','123 Harry Street'),
    new obj('Treasurer','Joe Bogs','123 Harry Street'),
    new obj('Secretary','Jane Doh','456 Harry Street'),
);

// array_unique compares the toString value if given objects
$unique = array_unique($objects);

或者,如果由于某种原因您不能在对象中使用 __toString,请编写您自己的唯一函数,该函数可以使用自定义函数进行比较,该函数根据需要返回 unique_id:

function custom_array_unique($array, $function){
    $res = array();
    foreach($array as $o){
        if(!isset($res[$function($o)])) {
            $res[$function($o)] = $o;
        }
    }
    return array_values($res);
}

$unique2 = custom_array_unique($objects, function($obj){
    return $obj->name . $obj->address;
});

var_dump($unique2);

【讨论】:

  • 但是如果 $type 不同,这三个对象不会都一样独特吗?
  • 不,我试过这个,想法是 array_unique 将每个对象与数组中的每个其他对象进行比较,如果它已经存在,它不会在结果中第二次生成它,因为array_unique 使用对象的 __toString() 函数(如果可用)来获取对象的更简单的字符串表示,然后比较字符串表示而不是对象本身,以适合您的想法的方式实现该方法,忽略类型会产生你预期的结果
  • 然而,这可能不是最优雅的解决方案,因为您可能希望将 toString 用于其他用途,这就是为什么我包含第二个示例,您可以在该类之外定义一个返回然后可以比较的特殊字符串。
  • 是的,现在说得通了,不幸的是我无法访问 __toString() 函数。
  • @joschua011 我喜欢你的第一个代码的想法。但我认为将所有内容都转换为 obj 类,然后获取唯一值,然后将它们转换回来,这有点过头了。
【解决方案3】:

你可以把type作为key,这样就不会重复了,如果你不想覆盖,你可以通过array_key_exists来验证它的存在,然后你可以@ 987654322@按要求获取订单,见下例:

$newArray = array();
foreach($objects as $object){
    if(!array_key_exists($object->name, $newArray)){
        $newArray[$object->name] = $object;
    }
}
$newArray = array_values($newArray);
echo '<pre>';
print_r($newArray);

【讨论】:

  • 投反对票一定要留下理由,如有错误,可以指正!
  • 除了代码中的语法错误之外,它也不会输出 OP 的预期输出。我想你错过了那部分:我想忽略“类型”
  • 我想你也错过了我评论中的这一部分:除了语法错误s
  • 那么请告诉我:$newArray(); 应该怎么做?而且您的代码输出仍然与 OP 的预期输出不匹配。 (顺便说一句:array_values($newArray); 并没有做你认为的事情)
猜你喜欢
  • 2021-05-25
  • 1970-01-01
  • 1970-01-01
  • 2020-10-22
  • 2011-12-13
  • 2011-06-29
  • 2017-06-18
  • 2011-01-04
相关资源
最近更新 更多