如何使用foreach循环,在最后一次迭代中执行不同的操作?

6
这可能是一个简单的问题,但是如何遍历数组,在每个元素上执行某些操作,直到最后一个元素并执行不同的操作?
我有一个名字的数组。我想输出由逗号分隔的名称列表。
Joe, Bob, Foobar 我不想在数组中的最后一个名称处添加逗号,也不想在数组中只有一个值(或没有值)时添加逗号。
更新:我不能使用implode(),因为我有一个User模型对象的数组,我需要从每个对象获取名称。
$users = array();
$users[] = new User();

foreach ($users as $user) {
    echo $user->name;
    echo ', ';
}

我如何实现这个并且仍然使用这些对象?
更新:我过于担心我在视图脚本中放置了多少行代码,所以我决定创建一个视图助手。以下是我的最终方案:
$array = array();
foreach($users as $user) {
    $array[] = $user->name;
}
$names = implode(', ', $array);

@Andrew,我在我的问题中更新了对你的更新的回答。 - Doug Neiner
8个回答

15

使用 implode 函数:

$names = array('Joe', 'Bob', 'Foobar');
echo implode(', ', $names); # prints: Joe, Bob, Foobar
为了澄清,如果数组中只有一个对象,则根本不会使用', '分隔符,并且将返回包含单个项目的字符串。
编辑:如果您有一个对象数组,并且想以除了带有测试的for循环之外的方式进行操作,可以这样做:
function get_name($u){ return $u->name; };
echo implode(', ', array_map('get_name', $users) ); # prints: Joe, Bob, Foobar

谢谢您的回答,不幸的是我不能使用implode()函数,因为数组包含对象。有没有其他方法可以实现同样的功能? - Andrew
2
在PHP 5.3+中,您甚至不必声明函数,只需匿名执行即可:implode(',',array_map(function($user){ return $user->name; },$users) - Jordan Running
我已经写了多年的PHP,从来没有想过这个问题,这是不好的吗? - Brendan Long
2
@Brendan,不是这样的。只是当你在使用Ruby之后开始使用PHP时,你会对Arrays有不同的看法 :) - Doug Neiner

6
$array = array('joe', 'bob', 'Foobar');
$comma_separated = join(",", $array);

输出:

joe,bob,Foobar


显然,join是implode的别名 :) - µBio
我个人更喜欢使用join,因为它不会让那些来自Java/Perl背景的人感到困惑。 - karim79
我知道!可惜的是,split不是explode的别名。因此在PHP中我只能使用explodeimplode,尽管它们的名称很糟糕 :) - Doug Neiner
谢谢你的回答,不幸的是我不能使用join(),因为数组包含对象。有没有其他方法可以实现同样的功能? - Andrew

3
有时您可能不想使用implode。然后的技巧是使用一个辅助变量来监视循环的第一次而不是最后一次。如下所示:
$names = array('Joe', 'Bob', 'Foobar');
$first = true;
$result = '';
foreach ($names as $name)
{
   if (!$first)
      $result .= ', ';
   else
      $first = false;

   $result .= $name;
}

那让我感到很困惑。 - Aditya M P

1

伪代码...

integer sigh=container.getsize();
sigh--;
integer gosh=0;
foreach element in container
{
  if(gosh!=sigh)
    dosomething();
  else 
    doLastElementStuff();
  gosh++;
}

看了所有其他答案,似乎自从我上次写PHP以来,它的语法变得更加丰富了 :D


我会因为你读了标题而给你一个+1,但是因为你没有读问题,我不得不给你一个-1 :) - Doug Neiner
啊,明白了。我一定是在编辑后不久就偶然发现了它。 - Doug Neiner

1

在编写SQL语句等内容时,我经常遇到这个问题。

$joiner = " ";
foreach ($things as $thing) {
    echo "  $joiner $thing \n";
    $joiner = ',';
}

由于某些原因,如果您将“,”、“AND”或“OR”视为在项目之前的选项/属性,则更容易解决逻辑问题。然后问题就变成了如何在第一行中抑制“,”。

只要空格不是问题,这很酷。但是这个概念很强大,你可以以不同的方式编写它来消除额外的空格。+1 - Doug Neiner

1

implode(', ', $array_of_names)

的意思是将 $array_of_names 数组中的元素用逗号和空格连接起来。

0

如果你追求微观优化,我个人认为最快的方法是:

  if(isset($names[1])) {
     foreach ($names as $name) {
       $result .= $name . ', ';
    }
    $result = substr($result, 0, -2);
  } else {
    $result = $names[0];
  }

isset($names[1]) 是检查数组(或字符串)长度最快的方法(尽管不太清晰)。在这种情况下,执行至少两个元素的检查。


你需要使用-2而不是-1来移除空格和逗号。 - Doug Neiner

0

实际上,我发现以稍微不同的方式创建逗号分隔文本更容易。虽然有点啰嗦,但可以减少函数调用。

<?php

$nameText = '';
for ($i = 0; $i < count($nameArray); $i++) {
    if ($i === 0) {
        $nameText = $nameArray[$i];
    } else {
        $nameText .= ',' . $nameArray[$i];
    }
}

它将逗号添加为每个名称的前缀,除非它是数组的第一个元素。我喜欢使用for而不是foreach,因为我可以轻松访问数组的当前索引和相邻元素。你也可以这样使用foreach

<?php

$nameText = '';
$nameCounter = 0;
foreach ($nameArray as $thisName) {
    if ($nameCounter === 0) {
        $nameText = $thisName;
        $nameCounter++;
    } else {
        $nameText .= ',' . $thisName;
    }
}

但是 count 在每次循环中都会重新计算,因此每个循环仍然有一个函数调用。此外,您还在每个循环中引入了一个 if 语句。 - Doug Neiner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接