可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to separate an array with comma and word.
This is the code that i make:
$array = array( 'user1', 'user2', 'user3', 'user4', 'user5' );
$last = array_pop( $array );
$string = count( $array ) ? implode( ", ", $array ) . " and " . $last : $last;
printf( 'Authors: %s', $string );
My code print this:
Authors: user1, user2, user3, user4 and user5
I successfully made a code to implode the array with a comma and search for the last key and separate it with a word 'and'.
But that's what I want but I failed after more than 2 days of work on this:
Authors: user1, user2, and user3 and 2 others.
回答1:
While I always look for the clever calculated process for handling a task like this, I'll offer a much more pedestrian alternative. (For the record, I hate writing a battery of if-elseif-else
conditions almost as much as I hate the verbosity of a switch-case
block.) For this narrow task, I am electing to abandon my favored array functions and conditionally print the values with their customized delimiters.
While this solution is probably least scalable on the page, it is likely to be the easiest to comprehend (relate the code to its generated output). If this is about "likes" or something, I don't really see a large demand for scalability -- but I could be wrong.
Pay close attention to the 2-count case. My solution delimits the elements with and
instead of ,
which seems more English/human appropriate.
Code: (Demo)
$arrays[] = array();
$arrays[] = array('user1');
$arrays[] = array('user1', 'user2');
$arrays[] = array('user1', 'user2', 'user3');
$arrays[] = array('user1', 'user2', 'user3', 'user4');
$arrays[] = array('user1', 'user2', 'user3', 'user4', 'user5');
foreach ($arrays as $i => $array) {
echo "TEST $i: ";
if (!$count = sizeof($array)) {
echo "nobody";
} elseif ($count == 1) {
echo $array[0];
} elseif ($count == 2) {
echo "{$array[0]} and {$array[1]}";
} elseif ($count == 3) {
echo "{$array[0]}, {$array[1]}, and {$array[2]}";
} else {
echo "{$array[0]}, {$array[1]}, {$array[2]}, and " , $count - 3, " other" , ($count != 4 ? 's' : '');
}
echo "\n---\n";
}
Output:
TEST 0: nobody
---
TEST 1: user1
---
TEST 2: user1 and user2
---
TEST 3: user1, user2, and user3
---
TEST 4: user1, user2, user3, and 1 other
---
TEST 5: user1, user2, user3, and 2 others
---
p.s. A more compact version of the same handling:
Code: (Demo)
if (!$count = sizeof($array)) {
echo "nobody";
} elseif ($count < 3) {
echo implode(' and ', $array);
} else{
echo "{$array[0]}, {$array[1]}";
if ($count == 3) {
echo ", and {$array[2]}";
} else {
echo ", {$array[2]}, and " , $count - 3, " other" , ($count != 4 ? 's' : '');
}
}
And finally, here's an approach that "doctors up" the array and prepends and
to the final element. I think anyway you spin this task, there's going to be a degree of convolution.
Code: (Demo)
$count = sizeof($array);
if ($count < 3) {
echo implode(' and ', $array);
} else {
if ($count == 3) {
$array[2] = "and {$array[2]}";
} else {
$more = $count - 3;
array_splice($array, 3, $more, ["and $more other" . ($more > 1 ? 's' : '')]);
}
echo implode(', ', $array);
}
回答2:
Here's one way to do it:
Start by imploding the first two array elements. (array_splice
will remove them from $array
.)
$string = implode(', ', array_splice($array, 0, 2));
Add the third one if it's there. (array_shift
will remove it from $array
too.)
if ($array) {
$string .= ', and ' . array_shift($array);
}
Count the rest and add them, if any are left.
if ($n = count($array)) {
$string .= " and $n other". ($n > 1 ? 's' : '');
// conditional pluralization
}
回答3:
There are several ways to do it, one simple way :
First you should get the numbers of elements in your array to see if it's more than 3 or not.
$count = count( $array) ;
Then if it's more than 3 , you can make your string:
if($count>3){
$string= $array[0] . 'and' . $array[1] . 'and' . $array[2] . 'and' . ($count - 3) . "others";
}else{
$last = array_pop( $array );
$string = count( $array ) ? implode( ", ", $array ) . " and " . $last : $last;
//I used exactly your code , you have several ways to do it
//Attention ... This code may not work when your array has only one element
}
printf( 'Authors: %s', $string );
If you want to know more about PHP arrays you can use this link , a quick tutorial
Or the documentation
回答4:
I suggest you to think your problem as a function that you can Unit-Test so it becomes easier to build and you can flexibilize your solution.
- Use counters to track your array: total, first chunk, tail
- Consider any special cases like 2 elements, 3 elements, etc.
- Get the last item with
array_pop
- Use
array_slice
to get the first chunk from the "take N" argument.
- Implode and concat as required to get the desired result
Here an example of how it could be.
<?php
function niceAuthorsPrint(array $authors, $takeCount){
$totalAuthors = count( $authors );
$tailCount = $totalAuthors - $takeCount;
$first = array_slice($authors, 0, $takeCount);
$othersLabel = $tailCount == 1 ? 'other' : 'others';
$string = implode( ", ", $first );
if($tailCount > 0){
$string .= " and " . $tailCount . ' ' . $othersLabel;
}
return $string;
}
// take 3
echo niceAuthorsPrint(array( 'user1', 'user2', 'user3', 'user4', 'user5' ), 3) ."\n";
// take 4
echo niceAuthorsPrint(array( 'user1', 'user2', 'user3', 'user4', 'user5' ), 4) ."\n";
// take 5
echo niceAuthorsPrint(array( 'user1', 'user2', 'user3', 'user4', 'user5' ), 5) ."\n";
?>
Will output:
user1, user2, user3 and 2 others
user1, user2, user3, user4 and 1 other
user1, user2, user3, user4, user5
Working example here
Alternative
An alternative for handling special cases and printing the last item value.
<?php
// array of authors, number of authors to take first
function niceAuthorsPrint(array $authors, $takeCount){
$totalAuthors = count( $authors );
if($totalAuthors >= 3 && $takeCount >= $totalAuthors)
{
$takeCount = 2;
}
if($totalAuthors == 2 && $takeCount >= $totalAuthors)
{
$takeCount = 1;
}
$last = array_pop($authors);
$tailCount = $totalAuthors - $takeCount;
$first = array_slice($authors, 0, $takeCount);
$othersLabel = $tailCount == 1 ? $last : $tailCount . ' others';
$string = implode( ", ", $first );
if($tailCount > 0){
$string .= " and " . $othersLabel;
}
return $string;
}
// take 3
echo niceAuthorsPrint(array( 'user1', 'user2', 'user3', 'user4', 'user5' ), 3) ."\n";
// take 4
echo niceAuthorsPrint(array( 'user1', 'user2', 'user3', 'user4', 'user5' ), 4) ."\n";
// take 5
echo niceAuthorsPrint(array( 'user1', 'user2', 'user3', 'user4', 'user5' ), 5) ."\n";
// take original count, take first three as default
echo niceAuthorsPrint(array( 'user1', 'user2', 'user3', 'user4', 'user5' ), 5) ."\n";
// take original count, take first three as default
echo niceAuthorsPrint(array( 'user1', 'user2', 'user3'), 3) ."\n";
// take original count, take first three as default
echo niceAuthorsPrint(array( 'user1', 'user2'), 2) ."\n";
Will print:
user1, user2, user3 and 2 others
user1, user2, user3, user4 and user5
user1, user2 and 3 others
user1, user2 and 3 others
user1, user2 and user3
user1 and user2
Feel free to adjust to your needs.
Working code example