Jak uzyskać pierwszą literę każdego słowa dla danego ciągu?
$string = "Community College District";
$result = "CCD";
Znalazłem metodę javascript, ale nie byłem pewien, jak przekonwertować ją na php.
Jak uzyskać pierwszą literę każdego słowa dla danego ciągu?
$string = "Community College District";
$result = "CCD";
Znalazłem metodę javascript, ale nie byłem pewien, jak przekonwertować ją na php.
What__about__this__sentence?lubWhat about.This sentence?
Odpowiedzi:
explode()na spacjach, używasz []notacji, aby uzyskać dostęp do wynikowych ciągów jako tablic:
$words = explode(" ", "Community College District");
$acronym = "";
foreach ($words as $w) {
$acronym .= $w[0];
}
Jeśli spodziewasz się, że wiele spacji może oddzielać słowa, przełącz się na preg_split()
$words = preg_split("/\s+/", "Community College District");
Lub jeśli na przykład znaki inne niż białe znaki ograniczają słowa ( -,_), użyj preg_split()również:
// Delimit by multiple spaces, hyphen, underscore, comma
$words = preg_split("/[\s,_-]+/", "Community College District");
preg_match_all("/[A-Z]/", ucwords(strtolower($string)), $matches);
Najlepszym sposobem, aby to osiągnąć, są wyrażenia regularne.
Pozwala podzielić to, co chcesz w logiczny sposób: chcesz, aby każdy znak z ciągu znajdował się na początku słowa. Najlepszym sposobem na zidentyfikowanie tych znaków jest wyszukanie tych znaków, które są poprzedzone białymi znakami.
Zaczynamy więc od spojrzenia wstecz na ten znak spacji, po którym następuje dowolny znak:
/(?<=\s)./
Spowoduje to znalezienie dowolnego znaku poprzedzonego spacją. Ale - pierwszy znak w ciągu to znak w ciągu, który chcesz wyodrębnić. A ponieważ jest to pierwszy znak w ciągu, nie może być poprzedzony spacją. Chcemy więc dopasować wszystko, co jest poprzedzone spacją lub pierwszym znakiem w ciągu, więc dodajemy potwierdzenie początku tematu :
/(?<=\s|^)./
Teraz jesteśmy coraz bliżej. Ale co, jeśli ciąg zawiera bloki z wieloma spacjami? A jeśli zawiera spację, po której następuje znak interpunkcyjny? Prawdopodobnie nie chcemy dopasować żadnego z nich, w tłuszczu prawdopodobnie chcemy dopasować tylko litery. Możemy to zrobić z klasą postaci [a-zA-Z] . I możemy sprawić, że wyrażenia nie będą rozróżniać wielkości liter za pomocą i modyfikatora .
Tak więc otrzymujemy:
/(?<=\s|^)[a-z]/i
Ale jak właściwie używamy tego w PHP? Cóż, chcemy dopasować wszystkie wystąpienia wyrażenia regularnego w ciągu, więc używamy (zgadłeś) preg_match_all():
$string = "Progress in Veterinary Science";
$expr = '/(?<=\s|^)[a-z]/i';
preg_match_all($expr, $string, $matches);
Teraz mamy wszystkie postacie, które chcieliśmy wyodrębnić. Aby skonstruować ciąg wynikowy, który pokazujesz, musimy połączyć je ponownie :
$result = implode('', $matches[0]);
... i musimy upewnić się, że wszystkie są pisane wielkimi literami :
$result = strtoupper($result);
I to naprawdę wszystko.
(?<=\b)zamiast (?<=\s|^), pozwoli to na przechwycenie początkowych liter słów oddzielonych myślnikami, kropkami itp. (W zasadzie znaki „inne niż słowo”, te, które nie pasują do \ w lub \ W), ale może też skończyć się przechwyceniem rzeczy, których nie chcesz.
Zakładając, że wszystkie słowa są podzielone spacjami, jest to odpowiednie rozwiązanie:
$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)(a właściwie - mb_substr($word, 0, 1, 'utf-8')) jest absolutną koniecznością, jeśli pracujesz na ciągach wielobajtowych. Użycie simple $word[0]spowoduje obcięcie wielobajtowej połowy znaku i podanie nieprawidłowego inicjału - jakiś dziwny symbol zamiast rzeczywistej litery. Jeśli określisz tę sytuację jako błąd, masz swoją odpowiedź! :]
Odpowiedzi jest wiele explode. Myślę, że użycie tej strtokfunkcji jest dużo bardziej eleganckim i oszczędzającym pamięć rozwiązaniem:
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);
Oto bardziej niezawodna i użyteczna funkcja, która obsługuje znaki UTF8 i opcję używania tylko słów pisanych wielką literą:
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);
explodesię do rozwiązania tego problemu jest to, co można nazwać naiwnością rozwiązanie . To tak, jakby używać algorytmu sortowania bąbelkowego tylko dlatego, że jest łatwy do wdrożenia.
foreach(explode(' ', $string) as $word) echo $word[0];? Łatwiejsze do zrozumienia na pierwszy rzut oka i bez straty czasu.
explodejest złe (wykonuje swoją pracę), ale że istnieje bardziej eleganckie określenie rozwiązania problemu. I nie używam słowa „elegancki” w sposób estetyczny, używam go w sposób techniczny.
Odpowiedź Michała Berkowskiego (i innych), uproszczona do jednej linii i działająca poprawnie na znakach wielobajtowych (tj. Tworzenie skrótu / inicjałów z niełacińskiego ciągu):
foreach(explode(' ', $words) as $word) $acronym .= mb_substr($word, 0, 1, 'utf-8');
Używanie mb_substr($word, 0, 1, 'utf-8'), zamiast $word[0]wydaje się być obowiązkowe, jeśli pracujesz z niełacińskimi, wielobajtowymi łańcuchami i znakami, np. Używając łańcuchów zakodowanych w UTF-8.
Lubię to
preg_match_all('#(?<=\s|\b)\pL#u', $String, $Result);
echo '<pre>' . print_r($Result, 1) . '</pre>';
<=?
\pL. Czy mógłbyś jednak dodać małe wyjaśnienie? Wolę nauczyć człowieka łowić ryby, niż po prostu go dać ;-)
Jak wyjaśnili inni, klasyczny sposób polega na iteracji po każdym słowie początkowego ciągu, zredukowaniu słowa do jego pierwszej litery i połączeniu tych pierwszych liter razem.
Oto metoda pomocnicza łącząca różne kroki.
/**
* @return string
*/
function getInitials($string = null) {
return array_reduce(
explode(' ', $string),
function ($initials, $word) {
return sprintf('%s%s', $initials, substr($word, 0, 1));
},
''
);
}
Uwaga: to zwróci pusty ciąg w przypadku, gdy podany ciąg jest pusty.
getInitials('Community College District')
ciąg „CCD” (długość = 3)
getInitials()
string '' (długość = 0)
getInitials('Lorem ipsum dolor sic amet')
ciąg „Lidsa” (długość = 5)
Oczywiście możesz dodać filtry do funkcji wywołania zwrotnego array_reduce(), na przykład strtoupper()jeśli wolisz tylko inicjały pisane wielkimi literami.
$str = 'I am a String!';
echo implode('', array_map(function($v) { return $v[0]; }, explode(' ', $str)));
// would output IaaS
Coś, co ugotowałem.
/**
* 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;
}
Dlaczego nie użyć do tego funkcji str_word_count ?
zmniejszyć tę tablicę do pierwszej litery
$ acronym = array_reduce (str_word_count ("Community College District", 1), function ($ res, $ w) {return $ res. $ w [0];});
Myślę, że musisz eksplodować i ponownie do nich dołączyć .....
<?php
$string = "Progress in Veterinary Science";
$pieces = explode(" ", $string);
$str="";
foreach($pieces as $piece)
{
$str.=$piece[0];
}
echo $str; /// it will result into "PiVS"
?>
Korzystając z fundacji Prateeks, oto prosty przykład z wyjaśnieniami
// 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'
Jeśli jest więcej spacji między dwiema literami w ciągu wejściowym, spróbuj tego.
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);
Alternatywa tego samego kodu
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);
Oto funkcja, która pobiera inicjały imienia i jeśli inicjały mają tylko jedną literę, zwraca pierwsze 2 litery imienia.
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);
}
Spróbuj tego-
$strs=explode(" ",$string);
foreach($strs as $str)
echo $str[0];
W przypadku, gdy będziesz to robić na dużych łańcuchach (lub nawet bezpośrednio z pliku), explode()nie jest to najlepszy sposób. Wyobraź sobie, ile pamięci zostanie zmarnowane, jeśli będziesz musiał podzielić łańcuch o wielkości 2 MB na pamięć.
Przy odrobinie więcej kodowania i (zakładając PHP >= 5.0) możesz łatwo zaimplementować Iteratorklasę PHP, która zrobi dokładnie to. Będzie to zbliżone do generatora w Pythonie i krótko mówiąc, oto kod:
/**
* 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 jeśli użyjesz go na nieco trudniejszym łańcuchu:
$a = new WordsIterator("Progress in Veterinary Science. And, make it !more! interesting!\nWith new line.");
foreach( $a as $i){
echo $i;
echo "\n";
}
Czy uzyskasz oczekiwany wynik:
Progress
in
Veterinary
Science
And
make
it
more
interesting
With
new
line
Możesz więc łatwo $i[0]pobrać pierwszą literę, prawdopodobnie widzisz, że jest to bardziej efektywne rozwiązanie niż dzielenie całego ciągu do pamięci (zawsze używaj tylko jak najmniejszej ilości pamięci). Możesz również łatwo zmodyfikować to rozwiązanie, aby działało z ciągłym czytaniem plików itp.
<?php $arr = explode(" ",$String);
foreach($arr as $s)
{
echo substr($s,0,1);
}
?>
najpierw rozbijam ciąg o spacje, a następnie podciągam pierwszy znak.
Spróbuj tego
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');
Lubię Reg Expression zamiast innych metod ekstrakcji ciągów, ale jeśli nie jesteś zaznajomiony z Reg Ex, to usłyszysz metodę wykorzystującą funkcję explode()PHP:
$string = "David Beckham";
$string_split = explode(" ", $string);
$inititals = $string_split[0][0] . $string_split[1][0];
echo $inititals;
Oczywiście powyższy kod będzie działał tylko dla nazwy zawierającej dwa słowa.
Ta odpowiedź https://stackoverflow.com/a/33080232/1046909, ale z obsługą ciągów wielobajtowych:
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;
}
}
Możesz użyć tej funkcji na podstawie zaakceptowanej odpowiedzi od @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;
}
Parametr $ length określa, ile znaków chcesz wyświetlić
STOSOWANIE:
$acronym = buildAcronym("Hello World", 2);