PHP - mengulangi karakter string

120

Apakah ada cara yang bagus untuk mengulang karakter string? Saya ingin bisa melakukan foreach, array_map, array_walk, array_filterdsb di karakter dari string.

Ketik casting / juggling tidak membawa saya ke mana pun (letakkan seluruh string sebagai satu elemen array), dan solusi terbaik yang saya temukan hanyalah menggunakan for loop untuk membangun array. Rasanya harus ada sesuatu yang lebih baik. Maksud saya, jika Anda dapat mengindeksnya, bukankah seharusnya Anda dapat mengulangnya juga?

Ini yang terbaik yang aku punya

function stringToArray($s)
{
    $r = array();
    for($i=0; $i<strlen($s); $i++) 
         $r[$i] = $s[$i];
    return $r;
}

$s1 = "textasstringwoohoo";
$arr = stringToArray($s1); //$arr now has character array

$ascval = array_map('ord', $arr);  //so i can do stuff like this
$foreach ($arr as $curChar) {....}
$evenAsciiOnly = array_filter( function($x) {return ord($x) % 2 === 0;}, $arr);

Apakah ada:

A) Sebuah cara untuk membuat string iterable
B) Cara yang lebih baik untuk membangun array karakter dari string (dan jika demikian, bagaimana dengan arah lainnya?)

Saya merasa seperti saya kehilangan sesuatu yang jelas di sini.

jon_darkstar
sumber
Mungkin Anda harus mengatakan lebih banyak tentang apa yang Anda coba capai ... sepertinya mungkin ada cara yang lebih baik untuk melakukannya dengan menggunakan operasi string normal.
Vinay Pai
1
tidak memiliki tujuan nyata di sini. hanya rasa ingin tahu yang saya mainkan. tampak aneh bahwa meskipun Anda dapat mengindeks pada string, Anda tidak dapat mengulanginya. Saya bingung bahkan memikirkan penggunaan contoh yang berarti, tetapi saya masih ingin tahu apakah ada cara untuk mengulangi karakter string tanpa membangun array karakter secara eksplisit
jon_darkstar
itu poin yang bagus, jelas contoh saya cukup dangkal. yaitu - sebagian besar apa pun yang Anda lakukan array_filterdalam pengertian ini bisa lebih baik dilakukan dengan fungsi string atau reg-ex
jon_darkstar
Memecahkan projecteuler.net/problem=20 mungkin menjadi contoh kasus penggunaan (meskipun agak dibuat-buat).
Nick Edwards
satu catatan, mengenai untuk ($ i = 0; $ i <strlen ($ s); $ i ++) Saya akan menyimpan strlen ($ s) dalam variabel sebelum perulangan, dengan cara ini Anda tidak akan memanggil strlen () lebih dari 1 kali
Amin

Jawaban:

176

Langkah 1: Ubah string menjadi array menggunakan str_splitfungsi

$array = str_split($your_string);

Langkah 2: lakukan loop melalui array yang baru dibuat

foreach ($array as $char) {
 echo $char;
}

Anda dapat memeriksa dokumen PHP untuk informasi lebih lanjut: str_split

SeaBrightSystems
sumber
hah wow. ya itu saja. dan tentu saja ledakan dapat melakukan ke arah lain. Saya akan menerima ini segera kecuali seseorang dapat menunjukkan cara untuk melakukan iterasi dengan benar
jon_darkstar
@jon_darkstar Saya tidak tahu aplikasi Anda, tetapi perhatikan bahwa setiap entri dalam array memiliki overhead yang signifikan (4bytes IIRC). Lewati itu, ini lebih 'cukup': nikic.github.com/2011/12/12/…
Daan Timmer
str_split() will split into bytes, rather than characters when dealing with a multi-byte encoded string.- Jadi str_splittidak bisa bekerja dengan Unicode
Selamat
85

Iterasi string:

for ($i = 0; $i < strlen($str); $i++){
    echo $str[$i];
}
Owen
sumber
7
Ini sepertinya jawaban yang lebih baik karena menjawab pertanyaan - yaitu bagaimana melakukan iterasi pada string dibandingkan dengan 'convert to array'.
Robin Andrews
2
LOL !!!!! Semuanya @OmarTariq. Ini jauh lebih efisien daripada jawaban yang diberikan.
0x476f72616e
5
Perhatikan bahwa Anda memanggil strlen()setiap iterasi. Bukan hal yang buruk, karena PHP memiliki panjang yang telah dihitung sebelumnya, tetapi masih merupakan pemanggilan fungsi. Jika Anda membutuhkan kecepatan, lebih baik simpan itu dalam variabel sebelum memulai loop.
Vilx-
2
Ini tidak baik untuk string multibyte, karena di sini kita mendapatkan offset byte, bukan simbol
setiap
2
@OmarTariq "Ini jawabannya. Apa yang salah dengan dunia ini?" .... Yang salah dengan dunia adalah bahwa dunia memiliki bahasa lain selain bahasa Inggris, fungsi ini seperti yang dikatakan oleh alvery akan mengulang byte dalam string, bukan karakter.
Akuntan م
20

Jika string Anda dalam Unicode, Anda harus menggunakan preg_splitdengan /upengubah

Dari komentar di dokumentasi php:

function mb_str_split( $string ) { 
    # Split at all position not after the start: ^ 
    # and not before the end: $ 
    return preg_split('/(?<!^)(?!$)/u', $string ); 
} 
Dawid Ohia
sumber
1
Untuk string multibyte, mb_splitlebih andal.
Élektra
12

Anda juga dapat mengakses $ s1 seperti array, jika Anda hanya perlu mengaksesnya:

$s1 = "hello world";
echo $s1[0]; // -> h
Moritur
sumber
6

Diperluas dari jawaban @SeaBrightSystems, Anda dapat mencoba ini:

$s1 = "textasstringwoohoo";
$arr = str_split($s1); //$arr now has character array
Jendela Susu
sumber
Saya tidak setuju, jawaban ini menambah nilai, ini memberikan contoh kerja tentang bagaimana str_split dapat bekerja dalam aplikasi PHP. @SeaBrightSystems hanya menautkan ke dokumentasi, yang terkadang tidak terlalu membantu ketika seseorang mencoba melihat bagaimana suatu fungsi dapat bekerja, diberikan sebuah contoh. Jika tidak, sebagian besar jawaban SO hanya akan berupa tautan ke php.net
kurdtpage
6

Bagi mereka yang mencari cara tercepat untuk melakukan iterasi string di php, saya sudah menyiapkan pengujian benchmark.
Metode pertama di mana Anda mengakses karakter string secara langsung dengan menentukan posisinya dalam tanda kurung dan memperlakukan string seperti array:

$string = "a sample string for testing";
$char = $string[4] // equals to m

Saya sendiri mengira yang terakhir adalah metode tercepat, tetapi saya salah.
Adapun metode kedua (yang digunakan dalam jawaban yang diterima):

$string = "a sample string for testing";
$string = str_split($string);
$char = $string[4] // equals to m

Metode ini akan menjadi lebih cepat karena kita menggunakan array yang sebenarnya dan tidak menganggapnya sebagai array.

Memanggil baris terakhir dari masing-masing metode di atas untuk 1000000waktu mengarah pada hasil pembandingan berikut:

Menggunakan string [i]
0.24960017204285 Seconds

Menggunakan str_split
0.18720006942749 Seconds

Artinya cara kedua jauh lebih cepat.

AmirHossein
sumber
3

Hmm ... Tidak perlu mempersulit. Dasar-dasar selalu bekerja dengan baik.

    $string = 'abcdef';
    $len = strlen( $string );
    $x = 0;

Arah Maju:

while ( $len > $x ) echo $string[ $x++ ];

Keluaran: abcdef

Arah Terbalik:

while ( $len ) echo $string[ --$len ];

Keluaran: fedcba

Abu
sumber
2
// Unicode Codepoint Escape Syntax in PHP 7.0
$str = "cat!\u{1F431}";

// IIFE (Immediately Invoked Function Expression) in PHP 7.0
$gen = (function(string $str) {
    for ($i = 0, $len = mb_strlen($str); $i < $len; ++$i) {
        yield mb_substr($str, $i, 1);
    }
})($str);

var_dump(
    true === $gen instanceof Traversable,
    // PHP 7.1
    true === is_iterable($gen)
);

foreach ($gen as $char) {
    echo $char, PHP_EOL;
}
masakielastik
sumber
Saya terkejut jawaban ini hanya mendapat 1 suara positif :( ini jawaban yang paling / satu-satunya dapat diandalkan di sini
Akuntan م
1

Sebagian besar jawaban lupa tentang karakter non Inggris !!!

strlenmenghitung BYTES, bukan karakter, itulah mengapa demikian dan fungsi saudara kandungnya berfungsi dengan baik dengan karakter bahasa Inggris, karena karakter bahasa Inggris disimpan dalam 1 byte dalam encoding UTF-8 dan ASCII, Anda perlu menggunakan fungsi string multibyte mb_*

Ini akan bekerja dengan karakter apa pun yang dikodekanUTF-8

// 8 characters in 12 bytes
$string = "abcdأبتث";

$charsCount = mb_strlen($string, 'UTF-8');
for($i = 0; $i < $charsCount; $i++){
    $char = mb_substr($string, $i, 1, 'UTF-8');
    var_dump($char);
}

Output ini

string(1) "a"
string(1) "b"
string(1) "c"
string(1) "d"
string(2) "أ"
string(2) "ب"
string(2) "ت"
string(2) "ث"
Akuntan م
sumber