Get the first letter of each word in a string
PhpStringPhp Problem Overview
How would I get the first letter of each word for a given string?
$string = "Community College District";
$result = "CCD";
I found the javascript method but wasn't sure how to convert it to php.
Php Solutions
Solution 1 - Php
explode()
on the spaces, then you use the []
notation to access the resultant strings as arrays:
$words = explode(" ", "Community College District");
$acronym = "";
foreach ($words as $w) {
$acronym .= $w[0];
}
If you have an expectation that multiple spaces may separate words, switch instead to preg_split()
$words = preg_split("/\s+/", "Community College District");
Or if characters other than whitespace delimit words (-,_
) for example, use preg_split()
as well:
// Delimit by multiple spaces, hyphen, underscore, comma
$words = preg_split("/[\s,_-]+/", "Community College District");
Solution 2 - Php
The best way to accomplish this is with regular expressions.
Lets break down what you want in a logical way: You want every character from the string is at the beginning of a word. The best way to identify those characters is to look for those characters that are preceded by white space.
So we start with a lookbehind for that space character, followed by any character:
/(?<=\s)./
This will find any character preceded by a space. But - the first character in the string is a character in the string is one you want extract. And because it's the first character in the string, it can't be preceded by a space. So we want to match anything preceded by a space or the first character in the string, so we add a start-of-subject assertion:
/(?<=\s|^)./
Now we are getting closer. But what if the string contains blocks of multiple spaces? What if it contains a space followed by a punctuation character? We probably don't want to match any of those, in fat we probably just want to match letters. We can do that with a character class [a-zA-Z]
. And we can make are expression case-insensitive using the i
modifier.
So we end up with:
/(?<=\s|^)[a-z]/i
But how do we actually use this in PHP? Well we want to match all occurrences of the regular expression within the string so we use (you guessed it) preg_match_all()
:
$string = "Progress in Veterinary Science";
$expr = '/(?<=\s|^)[a-z]/i';
preg_match_all($expr, $string, $matches);
Now we have all the characters we wanted to extract. To construct the result string you show, we need to join them together again:
$result = implode('', $matches[0]);
...and we need to ensure that they are all upper-case:
$result = strtoupper($result);
And that's really all there is to it.
Here's a slightly compressed version, using the alternative regex from Leigh's comment to "capture the initial letters of words separated by hyphens, full stops, etc." (rather than only spaces.)
$str="Foo Bar";
preg_match_all('/(?<=\b)[a-z]/i',$str,$matches);
$result=strtoupper(implode('',$matches[0]));
Solution 3 - Php
Assuming the words are all split by spaces, this is a suitable solution:
$string = "Progress in Veterinary Science";
function initials($str) {
$ret = '';
foreach (explode(' ', $str) as $word)
$ret .= strtoupper($word[0]);
return $ret;
}
echo initials($string); // would output "PIVS"
Solution 4 - Php
There are a lot of explode
answers. I think using the strtok
function is a much more elegant and memory-efficient solution:
function createAcronym($string) {
$output = null;
$token = strtok($string, ' ');
while ($token !== false) {
$output .= $token[0];
$token = strtok(' ');
}
return $output;
}
$string = 'Progress in Veterinary Science';
echo createAcronym($string, false);
Here is a more robust and useful function, which supports UTF8 characters and the option to only use the capitalized words:
function createAcronym($string, $onlyCapitals = false) {
$output = null;
$token = strtok($string, ' ');
while ($token !== false) {
$character = mb_substr($token, 0, 1);
if ($onlyCapitals and mb_strtoupper($character) !== $character) {
$token = strtok(' ');
continue;
}
$output .= $character;
$token = strtok(' ');
}
return $output;
}
$string = 'Leiðari í Kliniskum Útbúgvingum';
echo createAcronym($string);
Solution 5 - Php
Michael Berkowski's (and others) answer, simplified to one line and working correctly on multi-byte characters (i.e. making abbreviation / initials out of non-Latin string):
foreach(explode(' ', $words) as $word) $acronym .= mb_substr($word, 0, 1, 'utf-8');
Using mb_substr($word, 0, 1, 'utf-8')
, instead of $word[0]
seems to be must, if you're working on non-Latin, multi-byte strings and characters, i.e. when using UTF-8 encoded strings.
Solution 6 - Php
As explained by others, classical way consist in iterating over each word of your initial string, reduce the word to its first letter, and combine those first letters together.
Here is a helper method combining the different steps.
/**
* @return string
*/
function getInitials($string = null) {
return array_reduce(
explode(' ', $string),
function ($initials, $word) {
return sprintf('%s%s', $initials, substr($word, 0, 1));
},
''
);
}
NB : this will return an empty string in case the given string is empty.
getInitials('Community College District')
> string 'CCD' (length=3)
getInitials()
> string '' (length=0)
getInitials('Lorem ipsum dolor sic amet')
> string 'Lidsa' (length=5)
Of course you can add filters to the callback function of array_reduce()
, such as strtoupper()
if you prefer only uppercased initials for instance.
Solution 7 - Php
$temp = explode(' ', $string);
$result = '';
foreach($temp as $t)
$result .= $t[0];
Solution 8 - Php
Like this
preg_match_all('#(?<=\s|\b)\pL#u', $String, $Result);
echo '<pre>' . print_r($Result, 1) . '</pre>';
Solution 9 - Php
$str = 'I am a String!';
echo implode('', array_map(function($v) { return $v[0]; }, explode(' ', $str)));
// would output IaaS
Solution 10 - Php
Something I've cooked up.
/**
* Return the first letter of each word in uppercase - if it's too long.
*
* @param string $str
* @param int $max
* @param string $acronym
* @return string
*/
function str_acronym($str, $max = 12, $acronym = '')
{
if (strlen($str) <= $max) return $str;
$words = explode(' ', $str);
foreach ($words as $word)
{
$acronym .= strtoupper(substr($word, 0, 1));
}
return $acronym;
}
Solution 11 - Php
function acronym( $string = '' ) {
$words = explode(' ', $string);
if ( ! $words ) {
return false;
}
$result = '';
foreach ( $words as $word ) $result .= $word[0];
return strtoupper( $result );
}
Solution 12 - Php
Why not using the str_word_count function for this?
-
get each word as a row in an array
-
reduce that array to the first letter
$acronym = array_reduce( str_word_count("Community College District", 1), function($res , $w){ return $res . $w[0]; } );
Solution 13 - Php
Assuming that the original string is properly built (trimmed and without double spaces), this is what I do:
$name = 'John Doe';
$initials = implode( '', array_map( function ( $part ) {
return strtoupper( $part['0'] );
}, explode( ' ', $name ) ) );
Basically, breaking the string into words, extracting & capitalizing the first character of a word, and gluing them back together.
Solution 14 - Php
I think you have to explode and join them back again .....
<?php
$string = "Progress in Veterinary Science";
$pieces = explode(" ", $string);
$str="";
foreach($pieces as $piece)
{
$str.=$piece[0];
}
echo $str; /// it will result into "PiVS"
?>
Solution 15 - Php
Using Prateeks foundation, here's a simple example with explanations
// initialize variables
$string = 'Capitalize Each First Word In A String';
$myCapitalizedString = '';
// here's the code
$strs=explode(" ",$string);
foreach($strs as $str) {
$myCapitalizedString .= $str[0];
}
// output
echo $myCapitalizedString; // prints 'CEFWIAS'
Solution 16 - Php
If there are more number of spaces between two letters in the input string then try this.
function first_letter($str)
{
$arr2 = array_filter(array_map('trim',explode(' ', $str)));
$result='';
foreach($arr2 as $v)
{
$result.=$v[0];
}
return $result;
}
$str=" Let's try with more spaces for fun . ";
echo first_letter($str);
Alternative of same code
function first_letter($str)
{
return implode('', array_map(function($v) { return $v[0]; },array_filter(array_map('trim',explode(' ', $str)))));;
}
$str=" Let's try with more spaces for fun . ";
echo first_letter($str);
Solution 17 - Php
Here's a function that gets you the initials of a name and if the initials are only 1 letter then it returns the first 2 letters of the first name.
function getNameInitials($name) {
preg_match_all('#(?<=\s|\b)\pL#u', $name, $res);
$initials = implode('', $res[0]);
if (strlen($initials) < 2) {
$initials = strtoupper(substr($name, 0, 2));
}
return strtoupper($initials);
}
Solution 18 - Php
Try this-
$strs=explode(" ",$string);
foreach($strs as $str)
echo $str[0];
Solution 19 - Php
<?php $arr = explode(" ",$String);
foreach($arr as $s)
{
echo substr($s,0,1);
}
?>
firstly I explode string by spaces then I substr first char.
Solution 20 - Php
Something like this should do the trick :
$string = 'Some words in a string';
$words = explode(' ', $string); // array of word
foreach($words as $word){
echo $word[0]; // first letter
}
Solution 21 - Php
For the case that you'll be doing this on large strings (or even directly from file) explode()
isn't the best way to do this. Imagine how much memory will get wasted if you have to split string 2MB large into memory.
With little more coding and (assuming PHP >= 5.0
) you can easily implement PHP's Iterator
class that will do exactly this. This will be close to generator in python and long story short, here's the code:
/**
* Class for CONTINOUS reading of words from string.
*/
class WordsIterator implements Iterator {
private $pos = 0;
private $str = '';
private $index = 0;
private $current = null;
// Regexp explained:
// ([^\\w]*?) - Eat everything non-word before actual word characters
// Mostly used only if string beings with non-word char
// ([\\w]+) - Word
// ([^\\w]+?|$) - Trailing thrash
private $re = '~([^\\w]*?)([\\w]+)([^\\w]+?|$)~imsS';
// Primary initialize string
public function __construct($str) {
$this->str = $str;
}
// Restart indexing
function rewind() {
$this->pos = 0;
$this->index = 0;
$this->current = null;
}
// Fetches current word
function current() {
return $this->current;
}
// Return id of word you are currently at (you can use offset too)
function key() {
return $this->index;
}
// Here's where the magic is done
function next() {
if( $this->pos < 0){
return;
}
$match = array();
++$this->index;
// If we can't find any another piece that matches... Set pos to -1
// and stop function
if( !preg_match( $this->re, $this->str, $match, 0, $this->pos)){
$this->current = null;
$this->pos = -1;
return;
}
// Skip what we have read now
$this->current = $match[2];
$this->pos += strlen( $match[1]) + strlen( $match[2]) + strlen($match[3]);
// We're trying to iterate past string
if( $this->pos >= strlen($this->str)){
$this->pos = -1;
}
}
// Okay, we're done? :)
function valid() {
return ($this->pos > -1);
}
}
And if you'll use it on a bit more challenging string:
$a = new WordsIterator("Progress in Veterinary Science. And, make it !more! interesting!\nWith new line.");
foreach( $a as $i){
echo $i;
echo "\n";
}
Will you get the expected result:
Progress
in
Veterinary
Science
And
make
it
more
interesting
With
new
line
So you can easily use $i[0]
to fetch first letter.You probably can see that this is more effective solution than splitting whole string into memory (always use only as little memory as possible). You also could easily modify this solution to work with continuous reading of files etc.
Solution 22 - Php
Try This
function initials($string) {
if(!(empty($string))) {
if(strpos($string, " ")) {
$string = explode(" ", $string);
$count = count($string);
$new_string = '';
for($i = 0; $i < $count; $i++) {
$first_letter = substr(ucwords($string[$i]), 0, 1);
$new_string .= $first_letter;
}
return $new_string;
} else {
$first_letter = substr(ucwords($string), 0, 1);
$string = $first_letter;
return $string;
}
} else {
return "empty string!";
}
}
echo initials('Thomas Edison');
Solution 23 - Php
I like Reg Expression over any other method of string extraction, but if you are unfamiliar with Reg Ex then hear is a method using the explode()
PHP function:
$string = "David Beckham";
$string_split = explode(" ", $string);
$inititals = $string_split[0][0] . $string_split[1][0];
echo $inititals;
Obviously the above code will only work on a name containing two words.
Solution 24 - Php
This answer https://stackoverflow.com/a/33080232/1046909 but with multibyte strings support:
if (!function_exists('str_acronym')) {
function str_acronym(string $str, int $min = -1, string $prefix = null): string
{
if (mb_strlen($str) <= $min) {
return $str;
};
$words = explode(' ', $str);
$acronym = strval($prefix);
foreach ($words as $word) {
if ($word = trim($word)) {
$acronym .= mb_strtoupper(mb_substr($word, 0, 1));
}
}
return $acronym;
}
}
Solution 25 - Php
You can use that function based on the accepted answer from @Michael Berkowski
function buildAcronym($string, $length = 1) {
$words = explode(" ", $string);
$acronym = "";
$length = (self::is_empty($string) || $length <= 0 ? 1 : $length);
foreach ($words as $i => $w) {
$i += 1;
if($i <= $length) {
$acronym .= $w[0];
}
}
return $acronym;
}
The $length parameter determines how many chars you want to display
USAGE:
$acronym = buildAcronym("Hello World", 2);
Solution 26 - Php
I'm a little underwhelmed by the suggested techniques here (despite having so many to choose from).
Assuming your input string is solely composed of whitespace delimited "words" (and you don't need to validate that the first character of each word is an actual letter), you can use this concise, multibyte safe technique to trim all letters after the first letter from each word and also discard the delimiting whitespaces.
Code: (Demo)
$string = "Let's observe obviously knowledgeable approaches that target helpful items succinctly";
echo preg_replace('~\S\K\S*\s*~u', '', $string);
Output:
Lookatthis
If you want to specifically target "letters", you can use \p{Ll}
and non-letters with \P{Ll}
(as replacements for \S
and \s
. The \K
restarts the fullstring match -- by effect, the matched first matched letter of each word is "set free" before matching more characters to be replaced by the empty string.
I see some other approaches on this page that are using lookbehinds to match the first letter of each word with preg_match_all('~(?<=\s|\b)\pL~u', ...)
, but notice the effect on fringe cases:
$string = "Let's check some fringe-cases: like @mentions and email@example";
#matches: ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
I cannot say if these would be desirable results, but if they were, then the pattern could be distilled to ~\b\pL~u
because the word boundary (\b
) is a zero-length assertion that doesn't require a lookbehind AND it covers every character that \s
could match.
I should also mention that any of the answers on this page that are accessing the first character by its offset (using array-like syntax like $word[0]
) or substr()
will fail whenever a multibyte character is encountered.