【问题标题】:Removing Keys In Associative Array Not Working删除关联数组中的键不起作用
【发布时间】:2012-12-03 23:32:28
【问题描述】:

我试图只保留某些键,并从外部 API 中删除其余键。我有一个数组(http://pastebin.com/vU8T4y7h),包含对象的“数据”:

foreach ($data as $media) {
    foreach (array_keys($media) as $media_key) {
        if ($media_key!=="created_time" && $media_key!=="likes" && $media_key!=="images" && $media_key!=="id") {
            unset($media[$media_key]);
        }
    }
}

在这种情况下,我试图只保留 created_timelikesimagesid 键,但是,上面的代码不起作用。关于为什么的任何想法?还有其他优雅的解决方案来实现同样的目标吗?

【问题讨论】:

    标签: php arrays associative-array


    【解决方案1】:

    这不起作用的原因是您没有从原始$data 对象中取消设置。您可以通过以下两种方式之一修复它。通过引用访问或更新您的 unset 以对原始 $data 对象进行操作。

    使用参考:

    foreach($data as &$media) {
    

    $data取消设置

    unset($data[$media][$media_key]);
    

    【讨论】:

      【解决方案2】:

      foreach 创建每个数组元素的副本,因此取消设置 $media[$media_key] 只会从副本中取消设置;并且您想从原始 $data 数组中取消设置:

      foreach ($data as $mediaRef => $media) {
          foreach (array_keys($media) as $media_key) {
              if ($media_key!=="created_time" && $media_key!=="likes" && $media_key!=="images" && $media_key!=="id") {
                  unset($data[$mediaRef][$media_key]);
              }
          }
      }
      

      或(通过引用)

      foreach ($data as &$media) {
          foreach (array_keys($media) as $media_key) {
              if ($media_key!=="created_time" && $media_key!=="likes" && $media_key!=="images" && $media_key!=="id") {
                  unset($media[$media_key]);
              }
          }
      }
      unset($media);
      

      【讨论】:

      • 从原始数据源中删除时需要 foreach k, v 而不是第一次迭代中的值。
      【解决方案3】:

      寻求优雅的解决方案:

      foreach ($data as $key => $media) {
          foreach (array_keys($media) as $media_key) {
              if (!in_array($media_key, array("created_time", "likes", "images", "id"))) {
                  unset($data[$key][$media_key]);
              }
          }
      }
      

      我会尽量避免在 foreach 循环中使用引用,因为您需要取消设置引用的变量。如果没有,就会发生难以检测的错误。

      【讨论】:

        【解决方案4】:

        您可以使用array_intersect_key 轻松完成此类操作:

        $keepTheseKeys = array_flip(array('created_time', 'likes', 'images', 'id'));
        
        foreach ($data as &$media) {
            $media = array_intersect_key($media, $keepTheseKeys);
        }
        unset($media);
        

        错误

        问题代码中的错误是您正在更新一个临时变量,或者通过引用传递媒体(参见上面的示例) - 或者引用原始变量:

        foreach ($data as $i => $media) {
            $data[$i] = ...
        

        【讨论】:

        • 我想你想要array_intersect_key 而不是array_diff_key
        • 确实是@NullUserException
        • 在循环之后也需要unset($media)
        • @Sven 这只有在你重用引用时才重要,这是一个糟糕的主意。
        • 我会说在 foreach 中使用引用首先是一件可怕的事情,但是 YMMV。
        【解决方案5】:

        首先,你不需要使用

        foreach (array_keys($media) as $media_key) {
        

        你可以使用

        foreach($media as $media_key => $media_value){
        

        改为

        但是对于您的问题,在第一行中,您正在遍历 $data,并且在每个循环中,将 $data 中的当前值分配给 $media。但是 media 与原始 $data 没有任何联系,因此在下一次迭代中,当新值从 $data 分配给 $media 时,它会被丢弃。

        你有两个选择:

        1. 使用参考:

          foreach($data as &$media) { // and so on... this should work, but i don't suggest it
          
        2. 在第一行写

          foreach($data as $media_k => $media) {
          

          在第四行写

          unset($data[$media_k][$media_key]); //
          

        【讨论】:

          猜你喜欢
          • 2018-09-16
          • 1970-01-01
          • 2010-12-17
          • 2014-07-24
          • 1970-01-01
          • 2016-03-11
          • 1970-01-01
          • 2013-06-22
          • 2013-03-03
          相关资源
          最近更新 更多