Отримайте першу букву кожного слова у рядку


81

Як отримати першу літеру кожного слова для даного рядка?

$string = "Community College District";
$result = "CCD";

Я знайшов метод javascript, але не був впевнений, як перетворити його на php.


1
Ви хочете знати, як отримати першу літеру вашого рядка, відповідно до того, як формулюється ваше запитання, або як отримати першу літеру кожного слова, як на вашому прикладі? Якщо перше: $ result = $ string [0].
Анонім

Ви впевнені, що кожне слово розділене єдиним пробілом? What__about__this__sentence?абоWhat about.This sentence?
Mike B

Чесно кажучи, розробіть свій власний сценарій на PHP.
Лев

Які символи можна кваліфікувати як роздільники? Пробіл, тире, підкреслення тощо?
Surreal Dreams

1
розгорніть рядок у пробіли, потім прокрутіть масив результатів, і оскільки кожен із них є рядком, ви можете використовувати $ string [0], щоб отримати перший символ, а потім просто об'єднати їх.
slash197

Відповіді:


136

explode()на пробілах, тоді ви використовуєте []позначення для доступу до результуючих рядків як масивів:

$words = explode(" ", "Community College District");
$acronym = "";

foreach ($words as $w) {
  $acronym .= $w[0];
}

Якщо ви очікуєте, що кілька пробілів можуть розділяти слова, замість цього перейдіть на preg_split()

$words = preg_split("/\s+/", "Community College District");

Або якщо символи, крім пробілів, обмежують слова ( -,_), наприклад, також використовуйте preg_split():

// Delimit by multiple spaces, hyphen, underscore, comma
$words = preg_split("/[\s,_-]+/", "Community College District");

14
До preg_match_all("/[A-Z]/", ucwords(strtolower($string)), $matches);
суті

46

Найкращий спосіб зробити це за допомогою регулярних виразів.

Давайте розберемо те, що ви хочете, логічним чином: ви хочете, щоб кожен символ із рядка був на початку слова. Найкращий спосіб ідентифікувати ці символи - це шукати тих символів, яким передує пробіл.

Отже, ми починаємо з огляду за цим просторовим символом, за яким слідує будь-який символ:

/(?<=\s)./

Це знайде будь-який символ, перед яким пробіл. Але - перший символ у рядку - це символ у рядку - це той, який ви хочете витягти. І оскільки це перший символ у рядку, перед ним не може стояти пробіл. Отже, ми хочемо зіставити все, що передує пробілу або першому символу в рядку, тому ми додаємо твердження про початок теми :

/(?<=\s|^)./

Зараз ми наближаємось. Але що, якщо рядок містить блоки з декількох пробілів? Що робити, якщо він містить пробіл, після якого ставиться розділовий знак? Ми, мабуть, не хочемо збігатись з жодною з них, в жирі ми, мабуть, просто хочемо збігатися з буквами. Ми можемо зробити це за допомогою класу персонажів [a-zA-Z] . І ми можемо зробити, щоб вираз не враховував регістр, використовуючи i модифікатор .

Отже, ми закінчуємо:

/(?<=\s|^)[a-z]/i

Але як насправді ми використовуємо це в PHP? Ну, ми хочемо зіставити всі випадки регулярного виразу всередині рядка, тому використовуємо (як ви вже здогадалися) preg_match_all():

$string = "Progress in Veterinary Science";

$expr = '/(?<=\s|^)[a-z]/i';
preg_match_all($expr, $string, $matches);

Тепер у нас є всі персонажі, яких ми хотіли витягти. Щоб побудувати результат, який ви показуєте, нам потрібно знову об’єднати їх :

$result = implode('', $matches[0]);

... і нам потрібно переконатися, що всі вони мають великі регістри :

$result = strtoupper($result);

І це насправді все.

Подивіться, як це працює


1
Якщо ви хочете, ви можете також використовувати (?<=\b)замість цього (?<=\s|^), це дозволить вам захопити початкові літери слів, розділені дефісами, крапками тощо (в основному "несловні" символи, ті, що не збігаються з \ w або \ W) але в кінцевому підсумку може захопити і речі, яких ви не хочете.
Лі

Ваше рішення дуже допомогло! Дякую !
yathrakaaran

1
Це однозначно має бути відповіддю. Надзвичайно детальний та чудово працює, дякую!
Стів Бауман

Це мені допомогло, але як щодо випадку $ string = "Прогрес у ветеринарній науці (округ Броуер)"; "B" відпадає. Будь-які думки
Кен

17

Якщо припустити, що всі слова розділені пробілами, це підходяще рішення:

$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"

Я думаю, що $ word [0] швидше substr ($ word, 0,1), то чому ви використовуєте substr ($ word, 0,1)?
Сер l33tname

1
Я просто не дуже довіряю рядкам як масивам. Раніше у
мене траплялися

Редагувати: TL; DR: просто старі звички
casraf

2
@LeonardChallis Я не знаю, чи Чен Асраф посилався на такий тип помилок, але використання substr($word,0,1)(або насправді - mb_substr($word, 0, 1, 'utf-8')) є абсолютно необхідним, якщо ви працюєте з багатобайтовими рядками. Використання простого $word[0]перерве багатобайтовий символ наполовину і дасть неправильний початковий знак - якийсь дивний символ замість фактичної букви. Якщо ви вважаєте цю ситуацію помилкою, тоді у вас є ваша відповідь! :]
трейдер

Будь-який метод або спосіб ігнорувати такі слова, як (in, the, of, a ...) і отримати вихід як "PVS" замість "PIVS"
Феніл Шах,

9

Відповідей дуже багато explode. Я думаю, що використання strtokфункції - набагато більш елегантне та ефективне для роботи з пам'яттю рішення:

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

Ось більш надійна та корисна функція, яка підтримує символи UTF8 та можливість використовувати лише слова з великої літери:

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

Я не згоден, ваш код масивний у порівнянні з методами вибуху.
Дейл

3
@Dale Ну, це говорить нам більше про вас, ніж про мій код - естетика - поганий спосіб оцінки коду. Використання explodeдля вирішення цієї проблеми - це те, що було б названо наївним рішенням . Це як використання алгоритму сортування за допомогою міхура лише тому, що його легко реалізувати.
Sverri M. Olsen

@MAssiveAmountsOfCode Я не згоден, чому робити щось із 13 рядків коду, чого можна досягти за 1 foreach(explode(' ', $string) as $word) echo $word[0];? Це легше зрозуміти з першого погляду, і це не марнотратство часу.
Дейл

Крім того, що є наївним у розділенні рядка слів, розділених пробілом, пробілом? Я думаю, що ваше зауваження говорить нам про те, що ви помпезний кодер, який не піддається перегляду коду.
Дейл

3
@Dale, я не хотів ображати тебе або здаватися помпезним. Це наївно, тому що розривання рядка створює масив, де він не потрібен. Токенізація рядка є більш елегантною, оскільки ви переходите через початковий рядок, який вимагає менше пам'яті. Я не кажу , що використання explodeє неправильним (він отримує роботу), але є більш елегантний скаже вирішення проблеми. І я не використовую слово «елегантний» естетично, я використовую його технічним способом.
Sverri M. Olsen

8

Відповідь Майкла Берковського (та інших), спрощена до одного рядка і правильно працює над багатобайтовими символами (тобто робить абревіатуру / ініціали з нелатинських рядків):

foreach(explode(' ', $words) as $word) $acronym .= mb_substr($word, 0, 1, 'utf-8');

Використовувати mb_substr($word, 0, 1, 'utf-8')замість, $word[0]здається, обов’язково, якщо ви працюєте над нелатинськими багатобайтними рядками та символами, тобто при використанні кодованих рядків UTF-8.



5

Подобається це

preg_match_all('#(?<=\s|\b)\pL#u', $String, $Result);
echo '<pre>' . print_r($Result, 1) . '</pre>';

Приємно. У мене проблема з першою літерою в коді. Який символ позначає першу літеру? <=?
Нарек

1
+1 за \pL. Не могли б ви додати невелике пояснення? Я вважаю за краще навчати чоловіка ловити рибу, а не просто давати його ;-)
DaveRandom

@Narek (? <=) Це позитивний погляд позаду цієї деталі
Вінстон,

@DaveRandom тут дані про цей символ
Вінстон,

@Winston Я знаю (хоча я взяв підхід KISS у своїй відповіді), я мав на увазі більше для OP ;-) але все одно дякую :-)
DaveRandom

5

Як пояснювали інші, класичний спосіб полягає у перегляді кожного слова вашого початкового рядка, зменшенні слова до першої літери та поєднанні цих перших букв разом.

Ось допоміжний метод, що поєднує різні етапи.

/**
 * @return string
 */
function getInitials($string = null) {
    return array_reduce(
        explode(' ', $string),
        function ($initials, $word) {
            return sprintf('%s%s', $initials, substr($word, 0, 1));
        },
        ''
    );
}

NB: це поверне порожній рядок у випадку, якщо даний рядок порожній.

getInitials('Community College District')

рядок 'CCD' (довжина = 3)

getInitials()

рядок '' (довжина = 0)

getInitials('Lorem ipsum dolor sic amet')

рядок 'Lidsa' (довжина = 5)

Звичайно, ви можете додати фільтри до функції зворотного виклику array_reduce(), наприклад, strtoupper()якщо ви віддаєте перевагу лише великі ініціали, наприклад.



3

Щось, що я приготував.

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

2
function acronym( $string = '' ) {
    $words = explode(' ', $string);
    if ( ! $words ) {
        return false;
    }
    $result = '';
    foreach ( $words as $word ) $result .= $word[0];
    return strtoupper( $result );
}

2

Чому б не використовувати для цього функцію str_word_count ?

  1. отримати кожне слово як рядок у масиві
  2. зменшити цей масив до першої літери

    $ акронім = array_reduce (str_word_count ("Community College District", 1), функція ($ res, $ w) {return $ res. $ w [0];});


1

Я думаю, вам доведеться вибухнути і приєднатися до них знову .....

<?php
$string  = "Progress in Veterinary Science";
$pieces = explode(" ", $string);
$str="";
foreach($pieces as $piece)
{
    $str.=$piece[0];
}    
echo $str; /// it will result into  "PiVS"
?>

1

Використовуючи основу Prateeks, ось простий приклад із поясненнями

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

Це моє перше рішення, розміщене на цьому сайті. HTH!
Роб Стоцький,

1

Якщо у вхідному рядку більше двох пробілів між двома літерами, спробуйте це.

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

Демо1

Альтернатива того ж коду

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

Демо2


1

Ось функція, яка отримує ініціали імені, і якщо ініціали складають лише 1 літеру, вона повертає перші 2 літери імені.

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


0

Щось на зразок цього повинно зробити трюк:

$string = 'Some words in a string';
$words = explode(' ', $string); // array of word
foreach($words as $word){
    echo $word[0]; // first letter
}

0

У випадку, коли ви будете робити це на великих рядках (або навіть безпосередньо з файлу), explode()це не найкращий спосіб це зробити. Уявіть, скільки пам’яті буде витрачено даремно, якщо вам доведеться розділити на пам’ять рядок розміром 2 МБ.

Трохи більше кодування і (припускаючи PHP >= 5.0) ви можете легко реалізувати Iteratorклас PHP, який буде робити саме це. Це буде близько до генератора в python і, якщо коротко, ось код:

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

І якщо ви будете використовувати його на дещо складнішому рядку:

$a = new WordsIterator("Progress in Veterinary Science. And, make it !more! interesting!\nWith new line.");
foreach( $a as $i){
    echo $i;
    echo "\n";
}

Чи отримаєте ви очікуваний результат:

Progress
in
Veterinary
Science
And
make
it
more
interesting
With
new
line

Таким чином, ви можете легко використовувати $i[0]для отримання першої літери. Ви, мабуть, бачите, що це більш ефективне рішення, ніж розбиття цілого рядка на пам'ять (завжди використовуйте лише якомога менше пам'яті). Ви також можете легко змінити це рішення для роботи з постійним читанням файлів тощо.



0

Спробуйте це

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

0

Мені подобається Reg Expression над будь-яким іншим способом вилучення рядків, але якщо ви не знайомі з Reg Ex, тоді hear - це метод, що використовує функцію explode()PHP:

$string = "David Beckham";
$string_split = explode(" ", $string);
$inititals = $string_split[0][0] . $string_split[1][0];
echo $inititals;

Очевидно, що наведений вище код працюватиме лише для імені, що містить два слова.


0

Ця відповідь https://stackoverflow.com/a/33080232/1046909, але з підтримкою багатобайтових рядків:

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

0

Ви можете використовувати цю функцію на основі прийнятої відповіді від @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;
}

Параметр $ length визначає, скільки символів ви хочете відобразити

ВИКОРИСТАННЯ:

$acronym = buildAcronym("Hello World", 2);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.