【问题标题】:Implode an array with ", " and add "and " before the last item用“,”插入一个数组,并在最后一项之前添加“和”
【发布时间】:2012-01-25 01:08:47
【问题描述】:

这个数组包含一个项目列表,我想把它变成一个字符串,但我不知道如何让最后一个项目在它之前有一个 &/and 而不是逗号。

1 => coke 2=> sprite 3=> fanta

应该变成

coke, sprite and fanta

这是常规的内爆函数:

$listString = implode(', ', $listArrau);

有什么简单的方法?

【问题讨论】:

  • 为什么不在数组的最后一个元素内爆之前切断其余元素?然后只需 .= 连接到您的字符串。

标签: php arrays


【解决方案1】:

适用于任意数量物品的长线:

echo join(' and ', array_filter(array_merge(array(join(', ', array_slice($array, 0, -1))), array_slice($array, -1)), 'strlen'));

或者,如果您真的更喜欢冗长:

$last  = array_slice($array, -1);
$first = join(', ', array_slice($array, 0, -1));
$both  = array_filter(array_merge(array($first), $last), 'strlen');
echo join(' and ', $both);

关键在于,这种切片、合并、过滤和连接可以正确处理所有种情况,包括 0、1 和 2 项,而无需额外的 if..else 语句。而且它恰好可以折叠成单线。

【讨论】:

  • +1 表示只需一行,-1 表示必须在 5 个月后返回并弄清楚它要做什么。
  • +1 表示聪明,但不是世界上最易读的解决方案:P
  • 哦,如果您愿意,可以将其分解为单独的步骤,只是这种方式不需要任何 ifs 或循环,并且都可以在一个表达式中完成.这就是为什么我称之为long-liner。当然,你可以把它放在一个名为joinWithLastSeparator(array $array, $separator = ' and ') 的函数中,这样你就知道它在 5 个月后做了什么。 :o)
  • 刚刚看到这篇文章,因为重复,得到了一个稍微肮脏但也略短的行。以为我只是把它扔在这里echo implode(" and ", array_filter(array_reverse([array_pop($array), implode(", ", $array)])));
  • 五年后,我不得不承认我可能会否决我自己的答案......我仍然为它是一个单一的表达而感到自豪,但是......嗯,是的... ;o)
【解决方案2】:

我不确定单排是解决这个问题的最优雅的解决方案。

这是我前段时间写的,并根据需要将其放入:

/**
 * Join a string with a natural language conjunction at the end. 
 * https://gist.github.com/angry-dan/e01b8712d6538510dd9c
 */
function natural_language_join(array $list, $conjunction = 'and') {
  $last = array_pop($list);
  if ($list) {
    return implode(', ', $list) . ' ' . $conjunction . ' ' . $last;
  }
  return $last;
}

您不必使用“and”作为您的连接字符串,它非常高效,适用于从 0 到无限数量的项目:

// null
var_dump(natural_language_join(array()));
// string 'one'
var_dump(natural_language_join(array('one')));
// string 'one and two'
var_dump(natural_language_join(array('one', 'two')));
// string 'one, two and three'
var_dump(natural_language_join(array('one', 'two', 'three')));
// string 'one, two, three or four'
var_dump(natural_language_join(array('one', 'two', 'three', 'four'), 'or'));

【讨论】:

  • +1 最简洁、最合乎逻辑且易于理解,并支持未知数量的项目。漂亮!
  • 比公认的答案更容易理解。
  • +1 表示该解决方案。可读性好。但是返回 null 对我来说有点奇怪。如果数组没有元素,我更喜欢返回空字符串。
【解决方案3】:

您可以弹出最后一项,然后将其与文本连接起来:

$yourArray = ('a', 'b', 'c');
$lastItem = array_pop($yourArray); // c
$text = implode(', ', $yourArray); // a, b
$text .= ' and '.$lastItem; // a, b and c

【讨论】:

  • 同样它不适用于 sizeof($yourArray) == 0。那么正确的解决方案是,首先检查数组的长度,然后执行上面的代码。如果 size==0,则什么也不做;如果 size==1,则返回第一项;否则执行上面的代码。
  • 添加条件if (count($yourArray) > 1)...谢谢:)
  • Enrique 的解决方案适用于 1 个元素(和 0 个元素),无需额外的 'if's。
【解决方案4】:

试试这个:

$str = array_pop($array);
if ($array)
    $str = implode(', ', $array)." and ".$str;

【讨论】:

  • 很好的简单解决方案 - 适用于 0、1、2 和 3+ 个元素,如果需要,可以调整为在最后一个元素之前有一个逗号
  • 唯一的问题是,如果有三个或更多元素,我希望在最后一个元素之前加一个逗号,但在某些情况下我可能只有两个元素,如果使用会添加一个错误的逗号相同的代码。我认为这在 99% 的情况下都有效,所以 +1。
【解决方案5】:

另一个可能的简短解决方案:

$values = array('coke', 'sprite', 'fanta');

$values[] = implode(' and ', array_splice($values, -2));
print implode(', ', $values);  // "coke, sprite and fanta"

它适用于任意数量的值。

【讨论】:

    【解决方案6】:

    我的首选,类似于 Enrique 的答案,但可以选择处理牛津逗号。

    public static function listifyArray($array,$conjunction='and',$oxford=true) {
        $last = array_pop($array);
        $remaining = count($array);
        return ($remaining ?
            implode(', ',$array) . (($oxford && $remaining > 1) ? ',' : '') . " $conjunction "
            : '') . $last;
    }
    

    【讨论】:

      【解决方案7】:

      我知道我迟到了答案,但这肯定是更好的方法吗?

      $list = array('breakfast', 'lunch', 'dinner');
      $list[count($list)-1] = "and " . $list[count($list)-1];
      echo implode(', ', $list);
      

      【讨论】:

      • 有一个缺点是在最后一个元素之前('and'之前)总是有一个逗号
      • 语法还是正确的。不过,我同意你的观点。 Enrique 的答案似乎与我的相似,但解决了这个问题:)
      • 当列表包含多个项目时有效,但当列表为动态时无效。 (使用 if 包装器轻松解决)
      【解决方案8】:

      这可以通过array_fillarray_map 完成。它也是单行的(似乎很多人喜欢它们)),但为了可读性而格式化:

      $string = implode(array_map(
          function ($item, $glue) { return $item . $glue; }, 
          $array,
          array_slice(array_fill(0, count($array), ', ') + ['last' => ' and '], 2)
      ));
      

      不是最佳解决方案,但尽管如此。

      这里是the demo

      【讨论】:

        【解决方案9】:

        试试这个

        $arr = Array("coke","sprite","fanta");
        $str = "";
        $lenArr = sizeof($arr);
        for($i=0; $i<$lenArr; $i++)
        {
            if($i==0)
                $str .= $arr[$i];
            else if($i==($lenArr-1))
                $str .= " and ".$arr[$i];
            else
                $str .= " , ".$arr[$i];
        }
        print_r($str);
        

        【讨论】:

          【解决方案10】:

          试试这个,

          <?php
          $listArray = array("coke","sprite","fanta");
          
          foreach($listArray as $key => $value)
          {
           if(count($listArray)-1 == $key)
            echo "and " . $value;
           else if(count($listArray)-2 == $key)
            echo $value . " ";
           else
            echo $value . ", ";
          }
          ?>
          

          【讨论】:

            【解决方案11】:

            我只是根据此页面上的建议对此进行了编码。我把我的伪代码留在了 cmets 中,以防有人需要它。我的代码与这里的其他代码不同,因为它处理不同大小的数组的方式不同,并且对三个或更多的列表使用牛津逗号符号。

                /**
                 * Create a comma separated list of items using the Oxford comma notation.  A
                 * single item returns just that item.  2 array elements returns the items
                 * separated by "and".  3 or more items return the comma separated list.
                 *
                 * @param array $items Array of strings to list
                 * @return string List of items joined by comma using Oxford comma notation
                 */
                function _createOxfordCommaList($items) {
                    if (count($items) == 1) {
                        // return the single name
                        return array_pop($items);
                    }
                    elseif (count($items) == 2) {
                        // return array joined with "and"
                        return implode(" and ", $items);
                    }
                    else {
                        // pull of the last item
                        $last = array_pop($items);
            
                        // join remaining list with commas
                        $list = implode(", ", $items);
            
                        // add the last item back using ", and"
                        $list .= ", and " . $last;
            
                        return $list;
                    }
                }
            

            【讨论】:

              【解决方案12】:

              此时这已经很老了,但我认为将我的解决方案添加到堆栈中不会有什么坏处。它的代码比其他解决方案多一点,但我可以接受。

              我想要一些灵活的东西,所以我创建了一个实用方法,允许设置最终分隔符应该是什么(例如,你可以使用 & 号)以及是否使用牛津逗号。它还可以正确处理包含 0、1 和 2 项的列表(这里的很多答案都没有这样做)

              $androidVersions = ['Donut', 'Eclair', 'Froyo', 'Gingerbread', 'Honeycomb', 'Ice Cream Sandwich', 'Jellybean', 'Kit Kat', 'Lollipop', 'Marshmallow'];
              
              echo joinListWithFinalSeparator(array_slice($androidVersions, 0, 1)); // Donut
              echo joinListWithFinalSeparator(array_slice($androidVersions, 0, 2)); // Donut and Eclair
              echo joinListWithFinalSeparator($androidVersions); // Donut, Eclair, Froyo, Gingerbread, Honeycomb, Ice Cream Sandwich, Jellybean, Kit Kat, Lollipop, and Marshmallow
              echo joinListWithFinalSeparator($androidVersions, '&', false); // Donut, Eclair, Froyo, Gingerbread, Honeycomb, Ice Cream Sandwich, Jellybean, Kit Kat, Lollipop & Marshmallow
              
              function joinListWithFinalSeparator(array $arr, $lastSeparator = 'and', $oxfordComma = true) {
                  if (count($arr) > 1) {
                      return sprintf(
                          '%s%s %s %s', 
                          implode(', ', array_slice($arr, 0, -1)),
                          $oxfordComma && count($arr) > 2 ? ',':'',
                          $lastSeparator ?: '', 
                          array_pop($arr)
                      );
                  }
              
                  // not a fan of this, but it's the simplest way to return a string from an array of 0-1 items without warnings
                  return implode('', $arr);
              }
              

              【讨论】:

                【解决方案13】:

                好的,所以这已经很老了,但我不得不说,我认为大多数答案都非常低效,有多个内爆或数组合并之类的东西,所有这些都比必要的 IMO 复杂得多。

                为什么不只是:

                implode(',', array_slice($array, 0, -1)) . ' and ' . array_slice($array, -1)[0]
                

                【讨论】:

                • 这会引起通知,因为您正在进行数组到字符串的转换。
                • 是的,昨天当我忘记自己的解决方案时,我注意到我自己,所以用谷歌搜索它!最后一部分缺少数组下标,我现在编辑并添加它。
                【解决方案14】:

                使用正则表达式的简单human_implode

                function human_implode($glue = ",", $last = "y", $elements = array(), $filter = null){
                    if ($filter) {
                        $elements = array_map($filter, $elements);
                    }
                
                    $str = implode("{$glue} ", $elements);
                
                    if (count($elements) == 2) {
                        return str_replace("{$glue} ", " {$last} ", $str);
                    }
                
                   return preg_replace("/[{$glue}](?!.*[{$glue}])/", " {$last}", $str);
                }
                
                print_r(human_implode(",", "and", ["Joe","Hugh", "Jack"])); // => Joe, Hugh and Jack
                

                【讨论】:

                  【解决方案15】:

                  我想出的另一个解决方案虽然稍微冗长一些。在我的情况下,我想让数组中的单词复数,所以这会在每个项目的末尾添加一个“s”(除非这个词已经以 's' 结尾:

                  $models = array("F150","Express","CR-V","Rav4","Silverado");
                  foreach($models as $k=>$model){ 
                      echo $model;
                      if(!preg_match("/s|S$/",$model)) 
                          echo 's'; // add S to end (if it doesn't already end in S)
                      if(isset($models[$k+1])) { // if there is another after this one.
                          echo ", "; 
                          if(!isset($models[$k+2])) 
                              echo "and "; // If this is next-to-last, add  ", and" 
                          }
                      }
                  }
                  

                  输出:

                  F150s, Express, CR-Vs, Rav4s, and Silverados
                  

                  【讨论】:

                    【解决方案16】:

                    它比 deceze 的解决方案更快,并且适用于巨大的数组(1M+ 元素)。这两种解决方案的唯一缺陷是由于使用了 array_filter,在少于三个元素的数组中与数字 0 的交互很差。

                    echo implode(' and ', array_filter(array_reverse(array_merge(array(array_pop($array)), array(implode(', ',$array))))));
                    

                    【讨论】:

                      猜你喜欢
                      • 2019-08-08
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-09-22
                      • 1970-01-01
                      相关资源
                      最近更新 更多