【问题标题】:Remove duplicates array from a multidimensional array in PHP从 PHP 中的多维数组中删除重复数组
【发布时间】:2019-09-04 19:41:09
【问题描述】:

如何从这个数组中过滤重复值?

实际上,对于相同的countrycity,数据是相同的- 只是人口发生了变化。

如何删除包含较高人口的数组?

$arr = array
(
    "100" => array(
        array(
            "country" => 'France',
            "city" => 'Paris',
            "population" => '1800000',
        ),
        array(
            "country" => 'France',
            "city" => 'Paris',
            "population" => '2000000',
        ),
        array(
            "country" => 'France',
            "city" => 'Toulouse',
            "population" => '500000',
        ),
    )
    "101" => array(
        array(
            "country" => 'Russia',
            "city" => 'Moscow',
            "population" => '144000000',
        )
    )
);

所以期望的输出应该是:

$arr = array
(
    "100" => array(
        array(
            "country" => 'France',
            "city" => 'Paris',
            "population" => '1800000'
        ),
        array(
            "country" => 'France',
            "city" => 'Toulouse',
            "population" => '500000'
        ),
    )
    "101" => array(
        array(
            "country" => 'Russia',
            "city" => 'Moscow',
            "population" => '144000000',
        )
    )
);

这是我尝试过的

$temp_array = [];
foreach ($array as &$v) {
    if (!isset($temp_array[$v['country']] && $temp_array[$v['city']]))
        $temp_array[$v[$key]] =& $v;
    }
$array = array_values($temp_array);
return $array;

【问题讨论】:

    标签: php arrays multidimensional-array duplicates


    【解决方案1】:

    您可以先使用array_reduce 过滤较低的人口(使用国家和城市的组合作为键)。然后分解它们并使用该最小值重置数组:

    foreach($arr as $k => &$ar) {
        $temp = array_reduce($ar, function ($carry, $item) {
            $key = $item["country"] . "###" . $item["city"];
            $carry[$key] = (isset($carry[$key]) && $item["population"] > $carry[$key]) ?  $carry[$key] : $item["population"];
            return $carry;
        }, []);
        $ar = [];
        foreach($temp as $k => $val) {
            list($country, $city) = explode("###", $k);
            $ar[] = array("country" => $country, "city" => $city, "population" => $val);
        }
    }
    

    现场示例:3lv4

    编辑

    您可以使用array_filter 代替foreach 循环来避免应对:

    $ar = array_filter($ar, function ($item) use ($mins) {
        $key = $item["country"] . "###" . $item["city"];
        return $mins[$key] == $item["population"];
     });
    

    【讨论】:

    • "city" = "Moscow" 不是问题的一部分
    • @Andreas 它是期望输出的一部分,所以假设 OP 有错字
    • 实际上,您的解决方案的问题是需要复制/粘贴要传递给新数组$ar[] = array("country" => $country, "city" => $city, "population" => $val); 的值。谢谢。
    • @Testy 如果副本打扰您使用array_filter - 编辑我的帖子
    • 哼。很好。你能更新链接吗?您还可以删除带有city 的部分吗?
    【解决方案2】:

    从外观上看,数组已经按国家分组,我假设每个数组元素只有来自同一国家的子数组。我还要说,无论如何,为每个国家/地区提供一个包含密钥的数组更明智,以便于访问和过滤线路,所以我会说

    $populations = [];
    
    foreach($array as $arr) {
    if(!isset($populations[$arr['country']])) $populations[$arr['country']] = [];//create an array entry for the country
         $cities = [];
         foreach($arr as $city) {
           if(!isset($cities[$city]) || $cities[$city]['population'] > $city['population']) $cities[$city] = ['population' => $city['population']];//you could put the value straight in, but this means if you expand later you could add extra fields to each cities info such as district, number of unemployed or whatever you're using this for
    
         }
    $populations[$arr['country']] = $cities;
    }
    

    这与您概述的输出略有不同,但我认为它会使进一步使用变得更简单,因为您可以访问特定国家的所有数据,然后访问其中的城市,而不必不断循环并检查孩子是否包含您所追求的国家/地区。

    我希望这是有道理的,我的未婚妻在我回答的同时试图和我谈论宜家,所以它可能不是 100% 完美,但至少会为你指明一个好的方向

    【讨论】:

      【解决方案3】:

      我做了两个嵌套循环,第一个获取包含特定键(例如 100 和 101)的所有内容的子数组。

      接下来我遍历数据,并保留一个具有两个级别的临时数组,第一个将国家作为键,第二个将作为跟踪人口最少的城市作为键。

      完成上述操作后,我会遍历临时数组以获取正确格式的国家、城市和人口,并将其附加到新数组中。然后我用之前的数组替换这个新获得的结果。

      <?php
      
      $arr = array
      (
          "100" => array(
              array(
                  "country" => 'France',
                  "city" => 'Paris',
                  "population" => '1800000',
              ),
              array(
                  "country" => 'France',
                  "city" => 'Paris',
                  "population" => '2000000',
              ),
              array(
                  "country" => 'France',
                  "city" => 'Toulouse',
                  "population" => '500000',
              ),
          ),
          "101" => array(
              array(
                  "country" => 'Russia',
                  "city" => 'Moscow',
                  "population" => '144000000',
              )
          )
      );
      
      foreach($arr as $key=>$subarr) {
          $tmp = array();
          foreach($subarr as $v) {
              $country = $v['country'];
              $city = $v['city'];
              $population = $v['population'];
      
              if(isset($tmp[$country])) {
                  if(isset($tmp[$country][$city])) {
                      if($tmp[$country][$city] > $population) {
                          $tmp[$country][$city] = $population;
                      }
                  } else {
                      $tmp[$country][$city] = $population;
                  }
              } else {
                  $tmp[$country] = array();
                  $tmp[$country][$city] = $population;
              }
          }
      
          $res = array();
              foreach($tmp as $country=>$cities) {
                  foreach($cities as $city=>$population) {
                      $res[] = array('country'=>$country,'city'=>$city,'population'=>$population);
                  }
              }
          $arr[$key] = $res;
      
      }
      print_r($arr);
      

      【讨论】:

        【解决方案4】:

        您可以使用国家和城市创建一个复合数组键,这样可以轻松跟踪您循环的内容。
        由于城市可能不在数组中,所以如果它需要不得到通知。

        foreach($arr as $key => $sub){
            foreach($sub as $item){
                if(isset($item['city'])){
                    if(!isset($res[$key][$item['country'] . $item['city']])) $res[$key][$item['country'] . $item['city']] = $item;
                    if($res[$key][$item['country'] . $item['city']] < $item['population']) $res[$key][$item['country'] . $item['city']] = $item;
                }else{
                    if(!isset($res[$key][$item['country']])) $res[$key][$item['country']] = $item;
                    if($res[$key][$item['country']] < $item['population']) $res[$key][$item['country']] = $item;
                }
            }
        }
        var_dump($res);
        

        输出:

        array(2) {
          [100]=>
          array(2) {
            ["FranceParis"]=>
            array(3) {
              ["country"]=>
              string(6) "France"
              ["city"]=>
              string(5) "Paris"
              ["population"]=>
              string(7) "1800000"
            }
            ["FranceToulouse"]=>
            array(3) {
              ["country"]=>
              string(6) "France"
              ["city"]=>
              string(8) "Toulouse"
              ["population"]=>
              string(6) "500000"
            }
          }
          [101]=>
          array(1) {
            ["Russia"]=>
            array(2) {
              ["country"]=>
              string(6) "Russia"
              ["population"]=>
              string(9) "144000000"
            }
          }
        }
        

        https://3v4l.org/KNuId

        如果您需要删除“FranceToulouse”等键,则只需再次循环数组并使用 array_values

        【讨论】:

        • 你好。谢谢你的时间。如何在 "FranceParis" 之类的键之后删除?谢谢。
        • 几秒钟前我将其添加到我的答案中。更新页面,它应该在那里
        • 抱歉,我看不到。它一直在呼应"FranceParis"
        • @Testy 我很高兴你接受了我的回答,但我相信 dWinders 的回答是更好的回答。这是你的决定,你应该接受你认为最好的答案,但我实际上认为你没有给他足够的机会。
        猜你喜欢
        • 2015-05-22
        • 2011-04-05
        • 1970-01-01
        • 1970-01-01
        • 2016-11-18
        • 2016-01-03
        • 2017-01-01
        • 2017-07-23
        • 1970-01-01
        相关资源
        最近更新 更多