90 votes

Implodez un tableau avec ", " et ajoutez " et " avant le dernier élément.

Ce tableau contient une liste d'éléments, et je veux le transformer en une chaîne de caractères, mais je ne sais pas comment faire pour que le dernier élément soit précédé d'un &/and au lieu d'une virgule.

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

devrait devenir

coke, sprite and fanta

Il s'agit de la fonction normale d'implosion :

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

Quel est le moyen le plus simple de le faire ?

4 votes

Pourquoi ne pas couper le dernier élément du tableau avant de faire imploser le reste ? Et puis juste .= concenre votre chaîne.

137voto

deceze Points 200115

Une doublure longue durée qui s'adapte à un grand nombre d'articles :

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

Ou, si vous vraiment Je préfère le caractère verbal :

$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);

Le fait est que ce découpage, cette fusion, ce filtrage et cette jonction manipulent todos les cas, y compris les éléments 0, 1 et 2, correctement sans supplément if..else déclarations. Et il se trouve qu'il peut être réduit à une seule ligne.

23 votes

+1 pour avoir tout sur une seule ligne, -1 pour devoir revenir dans 5 mois et comprendre ce qu'il essaie de faire.

3 votes

+1 pour l'intelligence, mais pas la solution la plus lisible du monde :P

4 votes

Oh, n'hésitez pas à le décomposer en étapes individuelles si vous le souhaitez, c'est juste que cette façon de faire ne nécessite aucune ifs ou des boucles, et tout cela peut être fait en une seule expression. C'est précisément pour cela que j'appelle ça une long-liner . Et bien sûr, on mettrait cela dans une fonction appelée joinWithLastSeparator(array $array, $separator = ' and ') afin que vous sachiez ce qu'il fait dans 5 mois :o)

113voto

Angry Dan Points 852

Je ne suis pas sûr qu'un "one liner" soit la solution la plus élégante à ce problème.

J'ai écrit ceci il y a un certain temps et je l'ajoute au besoin :

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

Vous n'êtes pas obligé d'utiliser "et" comme chaîne de jonction, c'est efficace et cela fonctionne avec un nombre d'éléments compris entre 0 et un nombre illimité :

// 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'));

Il est facile à modifier pour inclure une virgule d'Oxford si vous le souhaitez :

function natural_language_join( array $list, $conjunction = 'and' ) : string {
    $oxford_separator = count( $list ) == 2 ? ' ' : ', ';
    $last = array_pop( $list );

    if ( $list ) {
        return implode( ', ', $list ) . $oxford_separator . $conjunction . ' ' . $last;
    }

    return $last;
}

8 votes

+1 Le plus propre, le plus logique et le plus facile à suivre, et prend en charge un nombre inconnu d'éléments. Magnifique !

2 votes

Beaucoup plus facile à comprendre que la réponse acceptée.

0 votes

+1 pour cette solution. Lisible et bonne. Cependant, renvoyer null me semble un peu étrange. Je préfère retourner une chaîne vide si le tableau n'a pas d'éléments.

31voto

JercSi Points 649

Vous pouvez faire sauter le dernier élément et le joindre ensuite au texte :

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

1 votes

De même, cela ne fonctionne pas avec sizeof($votreTableau) == 0. Alors la solution correcte sera de vérifier d'abord la longueur du tableau et ensuite d'exécuter le code ci-dessus. si size==0, alors ne faites rien ; si size==1, retournez le premier élément ; sinon exécutez le code ci-dessus.

7 votes

Cela fonctionne comme un charme quand on ajoute une condition if (count($yourArray) > 1) ... Merci :)

0 votes

La solution d'Enrique fonctionne pour 1 élément (et 0 élément) sans "si" supplémentaire.

14voto

Enrique Points 73

Essayez ça :

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

0 votes

Bonne solution simple - fonctionne pour 0, 1, 2 et 3+ éléments, et peut être adaptée pour avoir une virgule avant le dernier élément si nécessaire.

1 votes

Le seul problème avec celui-ci est que je veux une virgule avant le dernier élément s'il y a trois éléments ou plus, mais je pourrais n'avoir que deux éléments dans certains cas, ce qui ajouterait une virgule erronée si j'utilise le même code. Je pense que cela fonctionnera dans 99% des situations, donc +1.

4voto

VisioN Points 62518

Une autre solution courte possible :

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

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

Il fonctionne bien avec n'importe quel nombre de valeurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X