Reputation: 4059
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.
Upvotes: 96
Views: 146958
Reputation: 270767
explode()
on the spaces, then you use an appropriate substring method to access the first character of each word.
$words = explode(" ", "Community College District");
$acronym = "";
foreach ($words as $w) {
$acronym .= mb_substr($w, 0, 1);
}
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");
Upvotes: 165
Reputation: 88697
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 "any word character" \w
escape sequence. And we can make are expression case-insensitive using the i
modifier as well as u
modifier to support utf-8 characters.
So we end up with:
/(?<=\s|^)\w/iu
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|^)\w/iu';
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 = mb_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)\w/iu',$str,$matches);
$result=mb_strtoupper(implode('',$matches[0]));
Upvotes: 53
Reputation: 439
Try this
$string = "Community College District";
echo $result = implode ('',array_map(function ($item) {return strtoupper($item[0]);} , explode(' ', $string)));
Upvotes: 0
Reputation: 48073
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.
Upvotes: 0
Reputation: 1056
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.
Upvotes: 2
Reputation: 151
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);
Upvotes: 0
Reputation: 1985
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;
}
}
Upvotes: 0
Reputation: 1719
Why not using the str_word_count function for this?
reduce that array to the first letter
$acronym = array_reduce( str_word_count("Community College District", 1), function($res , $w){ return $res . $w[0]; } );
Upvotes: 2
Reputation: 1168
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);
}
Upvotes: 1
Reputation: 5304
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.
Upvotes: 10
Reputation:
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;
}
Upvotes: 3
Reputation: 21
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);
Upvotes: 1
Reputation: 582
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.
Upvotes: 0
Reputation: 17515
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.
Upvotes: 9
Reputation: 21694
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"
Upvotes: 20
Reputation: 156
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'
Upvotes: 1
Reputation: 20270
$str = 'I am a String!';
echo implode('', array_map(function($v) { return $v[0]; }, explode(' ', $str)));
// would output IaaS
Upvotes: 3
Reputation: 1
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');
Upvotes: 0
Reputation: 20286
<?php $arr = explode(" ",$String);
foreach($arr as $s)
{
echo substr($s,0,1);
}
?>
firstly I explode string by spaces then I substr first char.
Upvotes: 0
Reputation: 21007
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.
Upvotes: 0
Reputation: 13283
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);
Upvotes: 10
Reputation: 1805
Like this
preg_match_all('#(?<=\s|\b)\pL#u', $String, $Result);
echo '<pre>' . print_r($Result, 1) . '</pre>';
Upvotes: 5
Reputation: 4363
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"
?>
Upvotes: 1
Reputation: 329
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
}
Upvotes: 0
Reputation: 595
Try this-
$strs=explode(" ",$string);
foreach($strs as $str)
echo $str[0];
Upvotes: 0
Reputation: 5931
function acronym( $string = '' ) {
$words = explode(' ', $string);
if ( ! $words ) {
return false;
}
$result = '';
foreach ( $words as $word ) $result .= $word[0];
return strtoupper( $result );
}
Upvotes: 2
Reputation: 8093
$temp = explode(' ', $string);
$result = '';
foreach($temp as $t)
$result .= $t[0];
Upvotes: 5