【问题标题】:Unsetting array values in a foreach loop [duplicate]在foreach循环中取消设置数组值[重复]
【发布时间】:2011-01-01 19:20:24
【问题描述】:

我设置了一个 foreach 循环来遍历我的数组,检查某个链接,如果找到它会从数组中删除该链接。

我的代码:

foreach($images as $image)
{
    if($image == 'http://i27.tinypic.com/29yk345.gif' ||
    $image == 'http://img3.abload.de/img/10nx2340fhco.gif' ||
    $image == 'http://i42.tinypic.com/9pp2456x.gif')
    {
        unset($images[$image]);
    }
}

但它不会删除整个数组。这可能与$images[$image] 有关,因为这不是数组条目的键,只有内容?有没有办法在不合并计数器的情况下做到这一点?

谢谢。

编辑:谢谢大家,但现在我遇到了另一个问题,数组条目实际上并没有被删除。

我的新代码:

foreach($images[1] as $key => $image)
{
    if($image == 'http://i27.tinypic.com/29yk345.gif')
    $image == 'http://img3.abload.de/img/10nx2340fhco.gif' ||
    $image == 'http://i42.tinypic.com/9pp2456x.gif')
    {
        unset($images[$key]);
    }
}

$images 现在实际上是一个二维数组,因此我需要 $images[1]。我已经检查过了,它成功地绕过了数组元素,有些元素实际上确实有一些我希望删除的 URL,但它们没有被删除。这是我的$images 数组:

Array
(
    [0] => Array
        (
            [0] => useless
            [1] => useless
            [2] => useless
            [3] => useless
            [4] => useless
        )

    [1] => Array
        (
            [0] => http://i27.tinypic.com/29yk345.gif
            [1] => http://img3.abload.de/img/10nx2340fhco.gif
            [2] => http://img3.abload.de/img/10nx2340fhco.gif
            [3] => http://i42.tinypic.com/9pp2456x.gif
        )

)

谢谢!

【问题讨论】:

  • 我还建议 if(in_array($image, array('i27.tinypic.com/29yk345.gif', 'img3.abload.de/img/10nx2340fhco.gif', 'i42.tinypic.com/9pp2456x.gif'))。使它更具可读性;)
  • 由于您更改了正在迭代的数组,因此需要在调用 unset - unset($images[1][$key]); 时反映出来
  • if 语句中的括号是错误的,但我猜这只是错字(否则你会收到错误消息)
  • "注意:当foreach第一次开始执行时,内部数组指针会自动重置为数组的第一个元素。这意味着您不需要在foreach循环之前调用reset()。如foreach 依赖于内部数组指针,在循环内更改它可能会导致意外行为。”取自php手册

标签: php arrays foreach unset


【解决方案1】:
foreach($images as $key => $image)
{
    if(in_array($image, array(
       'http://i27.tinypic.com/29ykt1f.gif',
       'http://img3.abload.de/img/10nxjl0fhco.gif',
       'http://i42.tinypic.com/9pp2tx.gif',
    ))
    {
        unset($images[$key]);
    }
}

【讨论】:

  • 感谢您的帮助,但实际上删除某些数组元素时我遇到了麻烦。请参阅第一篇文章中的编辑 :)
  • 那就试试unset($images[1][$key]);
【解决方案2】:

试试看:

foreach ($images[1] as $key => &$image) {
    if (yourConditionGoesHere) {
        unset($images[1][$key])
    }
}
unset($image); // detach reference after loop  

通常,foreach 对您的数组的副本进行操作,因此您所做的任何更改都是针对该副本进行的,并且不会影响实际的数组。

所以你需要通过$images[$key]取消设置值;

&$image 上的引用可防止循环创建会浪费内存的数组副本。

【讨论】:

  • 谢谢。我认为您所说的与我的问题有关(请参阅编辑)。即使我添加了&,但它仍然不起作用。
  • "&$image 上的引用防止循环创建会浪费内存的数组副本。"
  • 循环之后你应该unset($image);
  • @lanDess 我找到了另一个来源:nikic.github.io/2015/05/05/… section "References" => 所以,好的,在 PHP7 中,这个问题已经解决了,使用引用不是性能问题
  • @IbrahimShendy 安全,以防您以后重用该变量;如果不是,它将修改数组的最后一个元素
【解决方案3】:

要回答最初的问题(编辑后),您需要 unset($images[1][$key]);

现在了解 PHP 工作原理的更多信息: 您可以在 foreach 循环中安全地取消设置数组的元素,对于数组项是否有 & 并不重要。请参阅此代码:

$a=[1,2,3,4,5];
foreach($a as $key=>$val)
{
   if ($key==3) unset($a[$key]);
}
print_r($a);

打印出来:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [4] => 5
)

如您所见,如果您在 foreach 循环中取消设置正确的内容,一切正常。

【讨论】:

    【解决方案4】:

    您可以使用数组元素的索引将其从数组中移除,下次使用$list变量时,您会看到数组发生了变化。

    试试这样的

    foreach($list as $itemIndex => &$item) {
    
       if($item['status'] === false) {
          unset($list[$itemIndex]);
       }
    
    }
    

    【讨论】:

    • 这不起作用,见下文。 stackoverflow.com/a/2008893/922522
    • 在此处查看此方法失败:ideone.com/Vv4DR8
    • @Justin 那是因为您要取消设置 $item 而不是列表中的项目。我分叉了你的代码,这很有效:ideone.com/SY0XC3
    • 你是对的。感谢@rolandow 解决这个问题!
    • 不要忘记在 foreach 循环之后使用unset($item)
    【解决方案5】:

    $image 在您的情况下是项目的值而不是键。也可以使用以下语法来获取密钥:

    foreach ($images as $key => $value) {
        /* … */
    }
    

    现在您可以使用unset($images[$key]) 删除该项目。

    【讨论】:

    • 这可能有效,但它仍会复制整个数组以执行 foreach 循环。所以这是浪费内存。如果我没记错的话,使用引用的方法(请参阅我的答案)也比每次发生未设置时解析键/值对更快。
    • 第二部分其实并不那么真实。对不起。通过引用取消设置当然不起作用。
    • @Techpriester: foreach 始终适用于内部副本。
    【解决方案6】:

    一种解决方案是使用项目的键来删除它们——在使用foreach 循环时,您可以同时使用键和值。

    例如:

    $arr = array(
        'a' => 123,
        'b' => 456,
        'c' => 789, 
    );
    
    foreach ($arr as $key => $item) {
        if ($item == 456) {
            unset($arr[$key]);
        }
    }
    
    var_dump($arr);
    

    最后会给你这个数组:

    array
      'a' => int 123
      'c' => int 789
    


    这意味着,就您而言,这样的事情应该可以解决问题:

    foreach($images as $key => $image)
    {
        if($image == 'http://i27.tinypic.com/29yk345.gif' ||
        $image == 'http://img3.abload.de/img/10nx2340fhco.gif' ||
        $image == 'http://i42.tinypic.com/9pp2456x.gif')
        {
            unset($images[$key]);
        }
    }
    

    【讨论】:

      【解决方案7】:
      foreach($images as $key=>$image) { if($image == 'http://i27.tinypic.com/29ykt1f.gif' || $image == 'http://img3.abload.de/img/10nxjl0fhco.gif' || $image == 'http://i42.tinypic.com/9pp2tx.gif') { unset($images[$key]); } }

      !!foreach($images as $key=>$image

      因为 $image 是值,所以 $images[$image] 没有意义。

      【讨论】:

      • 失败。您应该使用code sample - 而不是blockquote。 ;)
      【解决方案8】:

      你还需要一个

      $i--;
      

      在每次未设置后不跳过一个元素/

      因为当您取消设置 $item[45] 时,for 循环中的下一个元素应该是 $item[45] - 在取消设置之前是 [46]。如果你不这样做,你总是会在取消设置后跳过一个元素。

      【讨论】:

      • 但是 unset() 不会改变数组索引,所以我认为这里不需要这个 $i-- 。如果使用了方法 array_splice() ,那么元素将被移动以覆盖删除的孔,并且 $i-- 是必要的。
      【解决方案9】:

      抱歉,回复晚了,我最近在使用 PHP 时遇到了同样的问题,发现当使用不使用 $key => $value 结构的数组时,在使用 foreach 循环时,您实际上会复制位置的值循环变量,在本例中为 $image。尝试使用此代码,它将解决您的问题。

      for ($i=0; $i < count($images[1]); $i++)
      {
      
          if($images[1][$i] == 'http://i27.tinypic.com/29yk345.gif' ||
      
          $images[1][$i] == 'http://img3.abload.de/img/10nx2340fhco.gif' ||
      
          $images[1][$i] == 'http://i42.tinypic.com/9pp2456x.gif')
      
          {
      
              unset($images[1][$i]);
      
          }
      
      }
      
      var_dump($images);die();
      

      【讨论】:

        猜你喜欢
        • 2011-03-04
        • 2013-10-23
        • 2011-02-20
        • 2017-05-05
        • 2015-03-07
        • 2019-05-11
        • 1970-01-01
        • 2023-03-07
        • 2013-07-18
        相关资源
        最近更新 更多