¿Cómo obtendría la primera letra de cada palabra para una cadena determinada?
$string = "Community College District";
$result = "CCD";
Encontré el método javascript pero no estaba seguro de cómo convertirlo a php.
explode()
en los espacios, luego usa la []
notación para acceder a las cadenas resultantes como matrices:
$words = explode(" ", "Community College District");
$acronym = "";
foreach ($words as $w) {
$acronym .= $w[0];
}
Si tiene la expectativa de que varios espacios pueden separar palabras, cambie a preg_split()
$words = preg_split("/\s+/", "Community College District");
O si, -,_
por ejemplo, caracteres distintos a los espacios en blanco delimitan palabras ( ), utilice preg_split()
también:
// Delimit by multiple spaces, hyphen, underscore, comma
$words = preg_split("/[\s,_-]+/", "Community College District");
preg_match_all("/[A-Z]/", ucwords(strtolower($string)), $matches);
La mejor forma de lograr esto es con expresiones regulares.
Analicemos lo que quiere de una manera lógica: quiere que todos los caracteres de la cadena estén al principio de una palabra. La mejor forma de identificar esos caracteres es buscar aquellos que estén precedidos por espacios en blanco.
Entonces comenzamos con una búsqueda hacia atrás para ese carácter de espacio, seguido de cualquier carácter:
/(?<=\s)./
Esto encontrará cualquier carácter precedido por un espacio. Pero, el primer carácter de la cadena es un carácter de la cadena que desea extraer. Y como es el primer carácter de la cadena, no puede ir precedido de un espacio. Así que queremos hacer coincidir cualquier cosa precedida por un espacio o el primer carácter de la cadena, por lo que agregamos una aserción de inicio de sujeto :
/(?<=\s|^)./
Ahora nos estamos acercando. Pero, ¿y si la cadena contiene bloques de varios espacios? ¿Qué pasa si contiene un espacio seguido de un carácter de puntuación? Probablemente no queremos hacer coincidir ninguno de esos, en grasa probablemente solo queremos hacer coincidir las letras. Podemos hacer eso con una clase de personaje [a-zA-Z]
. Y podemos hacer que una expresión no distinga entre mayúsculas y minúsculas usando el i
modificador .
Entonces terminamos con:
/(?<=\s|^)[a-z]/i
Pero, ¿cómo usamos esto en PHP? Bueno, queremos hacer coincidir todas las apariciones de la expresión regular dentro de la cadena, así que usamos (lo adivinó) preg_match_all()
:
$string = "Progress in Veterinary Science";
$expr = '/(?<=\s|^)[a-z]/i';
preg_match_all($expr, $string, $matches);
Ahora tenemos todos los personajes que queríamos extraer. Para construir la cadena de resultados que muestra, debemos unirlos nuevamente :
$result = implode('', $matches[0]);
... y debemos asegurarnos de que estén en mayúsculas :
$result = strtoupper($result);
Y eso es realmente todo lo que hay que hacer.
(?<=\b)
lugar de (?<=\s|^)
, esto le permitiría capturar las letras iniciales de las palabras separadas por guiones, puntos, etc. (básicamente, caracteres "que no son palabras", aquellos que no coincidirían con \ w o \ W), pero también podría terminar capturando cosas que no desea.
Suponiendo que todas las palabras están divididas por espacios, esta es una solución adecuada:
$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"
substr($word,0,1)
(o en realidad - mb_substr($word, 0, 1, 'utf-8')
) es una necesidad absoluta, si está operando en cadenas de varios bytes. El uso de simple $word[0]
cortará la mitad de un carácter de varios bytes y le dará una inicial incorrecta: algún símbolo extraño en lugar de la letra real. Si se refiere a esta situación como un error, ¡ahí tiene su respuesta! :]
Hay muchas explode
respuestas. Creo que usar la strtok
función es una solución mucho más elegante y eficiente en memoria:
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);
Aquí hay una función más robusta y útil, que admite caracteres UTF8 y la opción de usar solo las palabras en mayúscula:
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);
explode
para resolver este problema es lo que se llamaría una solución ingenua . Es como usar el algoritmo de clasificación de burbujas solo porque es fácil de implementar.
foreach(explode(' ', $string) as $word) echo $word[0];
? Más fácil de entender de un vistazo y no es una pérdida de tiempo.
explode
sea incorrecto (hace el trabajo), pero que hay una palabra más elegante para resolver el problema. Y no estoy usando la palabra "elegante" de manera estética, la estoy usando de manera técnica.
La respuesta de Michael Berkowski (y otros), simplificada a una línea y funcionando correctamente con caracteres de varios bytes (es decir, haciendo abreviaturas / iniciales de una cadena no latina):
foreach(explode(' ', $words) as $word) $acronym .= mb_substr($word, 0, 1, 'utf-8');
Usar mb_substr($word, 0, 1, 'utf-8')
, en lugar de $word[0]
parece ser obligatorio, si está trabajando en cadenas y caracteres no latinos, de múltiples bytes, es decir, cuando usa cadenas codificadas en UTF-8.
$temp = explode(' ', $string);
$result = '';
foreach($temp as $t)
$result .= $t[0];
Me gusta esto
preg_match_all('#(?<=\s|\b)\pL#u', $String, $Result);
echo '<pre>' . print_r($Result, 1) . '</pre>';
<=
?
\pL
. Sin embargo, ¿podrías agregar una pequeña explicación? Prefiero enseñarle a pescar a un hombre en lugar de simplemente darle uno ;-)
Como explicaron otros, la forma clásica consiste en iterar sobre cada palabra de su cadena inicial, reducir la palabra a su primera letra y combinar esas primeras letras juntas.
Aquí hay un método auxiliar que combina los diferentes pasos.
/**
* @return string
*/
function getInitials($string = null) {
return array_reduce(
explode(' ', $string),
function ($initials, $word) {
return sprintf('%s%s', $initials, substr($word, 0, 1));
},
''
);
}
NB: esto devolverá una cadena vacía en caso de que la cadena dada esté vacía.
getInitials('Community College District')
cadena 'CCD' (longitud = 3)
getInitials()
cadena '' (longitud = 0)
getInitials('Lorem ipsum dolor sic amet')
cadena 'Lidsa' (longitud = 5)
Por supuesto, puede agregar filtros a la función de devolución de llamada de array_reduce()
, por ejemplo, strtoupper()
si prefiere solo las iniciales en mayúscula, por ejemplo.
$str = 'I am a String!';
echo implode('', array_map(function($v) { return $v[0]; }, explode(' ', $str)));
// would output IaaS
Algo que he preparado.
/**
* 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;
}
function acronym( $string = '' ) {
$words = explode(' ', $string);
if ( ! $words ) {
return false;
}
$result = '';
foreach ( $words as $word ) $result .= $word[0];
return strtoupper( $result );
}
Creo que tienes que explotar y unirte a ellos de nuevo .....
<?php
$string = "Progress in Veterinary Science";
$pieces = explode(" ", $string);
$str="";
foreach($pieces as $piece)
{
$str.=$piece[0];
}
echo $str; /// it will result into "PiVS"
?>
Usando la base Prateeks, aquí hay un ejemplo simple con explicaciones
// 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'
Si hay más espacios entre dos letras en la cadena de entrada, intente esto.
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);
Alternativa del mismo código
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);
Aquí hay una función que le da las iniciales de un nombre y si las iniciales son solo 1 letra, entonces devuelve las 2 primeras letras del nombre.
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);
}
¿Por qué no usar la función str_word_count para esto?
reducir esa matriz a la primera letra
$ acronym = array_reduce (str_word_count ("Community College District", 1), function ($ res, $ w) {return $ res. $ w [0];});
Prueba esto-
$strs=explode(" ",$string);
foreach($strs as $str)
echo $str[0];
Algo como esto debería funcionar:
$string = 'Some words in a string';
$words = explode(' ', $string); // array of word
foreach($words as $word){
echo $word[0]; // first letter
}
En el caso de que haga esto en cadenas grandes (o incluso directamente desde el archivo) explode()
no es la mejor manera de hacerlo. Imagínese cuánta memoria se desperdiciará si tiene que dividir una cadena de 2 MB en memoria.
Con un poco más de codificación y (asumiendo PHP >= 5.0
) puede implementar fácilmente la Iterator
clase de PHP que hará exactamente esto. Esto estará cerca del generador en Python y, en pocas palabras, aquí está el código:
/**
* 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);
}
}
Y si lo usa en una cadena un poco más desafiante:
$a = new WordsIterator("Progress in Veterinary Science. And, make it !more! interesting!\nWith new line.");
foreach( $a as $i){
echo $i;
echo "\n";
}
Obtendrá el resultado esperado:
Progress
in
Veterinary
Science
And
make
it
more
interesting
With
new
line
Por lo tanto, puede usarlo fácilmente $i[0]
para buscar la primera letra. Probablemente pueda ver que esta es una solución más efectiva que dividir la cadena completa en la memoria (siempre use solo la menor cantidad de memoria posible). También puede modificar fácilmente esta solución para que funcione con la lectura continua de archivos, etc.
<?php $arr = explode(" ",$String);
foreach($arr as $s)
{
echo substr($s,0,1);
}
?>
En primer lugar, exploto la cadena por espacios y luego hago una subestación del primer carácter.
Prueba esto
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');
Me gusta Reg Expression sobre cualquier otro método de extracción de cadenas, pero si no está familiarizado con Reg Ex, escuche que es un método que usa la explode()
función PHP:
$string = "David Beckham";
$string_split = explode(" ", $string);
$inititals = $string_split[0][0] . $string_split[1][0];
echo $inititals;
Obviamente, el código anterior solo funcionará con un nombre que contenga dos palabras.
Esta respuesta https://stackoverflow.com/a/33080232/1046909 pero con soporte de cadenas multibyte:
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;
}
}
Puede usar esa función según la respuesta aceptada de @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;
}
El parámetro $ length determina cuántos caracteres desea mostrar
USO:
$acronym = buildAcronym("Hello World", 2);
What__about__this__sentence?
oWhat about.This sentence?