Внушить массив с помощью "," и добавить "и" перед последним элементом

Этот массив содержит список элементов, и я хочу превратить его в строку, но я не знаю, как сделать так, чтобы последний элемент имел символ &/и перед ним вместо запятой.

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

должен стать

coke, sprite and fanta

Это обычная функция взрыва:

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

Какой простой способ сделать это?

Ответ 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 операторов. И это, случается, сворачивается в однострочный.

Ответ 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;
}

Вам не нужно использовать "и" в качестве вашей строки соединения, она эффективна и работает с чем угодно: от 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'));

Ответ 3

Вы можете поместить последний элемент, а затем присоединить его к тексту:

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

Ответ 4

Попробуйте следующее:

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

Ответ 5

Еще одно возможное короткое решение:

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

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

Он отлично работает с любым количеством значений.

Ответ 6

Я знаю, что им нужно поздно ответить, но, конечно, это лучший способ сделать это?

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

Ответ 7

Мой переход, похожий на ответ Энрике, но при желании обрабатывает оксфордскую запятую.

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;
}

Ответ 8

Попробуйте это,

<?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 . ", ";
}
?>

Ответ 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

Я просто закодировал это на основе предложений на этой странице. Я оставил в своем псевдокоде комментарии в том случае, если кому-то это понадобилось. Мой код отличается от других здесь, поскольку он обрабатывает различные размеры массивов по-разному и использует нотацию запятой Оксфорда для списков из трех или более.

    /**
     * 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;
        }
    }

Ответ 11

Это довольно старый момент, но я подумал, что не может помешать добавить мое решение в кучу. Это немного больше кода, чем другие решения, но я в порядке с этим.

Мне нужно что-то с некоторой гибкостью, поэтому я создал метод утилиты, который позволяет установить, какой должен быть конечный разделитель (например, вы могли бы использовать амперсанд) и использовать или не использовать запятую Оксфорда. Он также правильно обрабатывает списки с 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 the simplest way to return a string from an array of 0-1 items without warnings
    return implode('', $arr);
}

Ответ 12

ОК, так что это становится довольно старым, но я должен сказать, что большинство ответов очень неэффективно с множественными слияниями модулей или массивов и т.д., все намного сложнее, чем необходимое IMO.

Почему не просто:

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

Ответ 13

Простой 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

Ответ 14

Это можно сделать с помощью array_fill и array_map. Это также однострочник (кажется, что многим они нравятся)), но форматированный для удобства чтения:

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

Не самое оптимальное решение, но тем не менее.

Вот демо.

Ответ 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

Он быстрее уничтожает решение и работает с огромными массивами (элементы 1M +). Единственным недостатком обоих решений является плохое взаимодействие с числом 0 в менее чем трех элементах массивов из-за использования array_filter.

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