Cách nhanh nhất là với một bitmask. Không có hàm chuỗi hoặc regex. PHP là một wrapper cho C, vì vậy chúng tôi có thể thao tác bit khá dễ dàng nếu bạn biết chức năng logic của bạn như OR, NOT, AND, XOR, NAND, vv ..:
function swapCase($string) {
for ($i = 0; $i < strlen($string); $i++) {
$char = ord($string{$i});
if (($char > 64 && $char < 91) || ($char > 96 && $char < 123)) {
$string{$i} = chr($char^32);
}
}
return $string;
}
Đây là những gì thay đổi nó:
$string{$i} = chr($char^32);
Chúng tôi có nhân vật thứ N trong $string
và thực hiện một XOR (^) nói với người phiên dịch để lấy giá trị số nguyên của $char
và trao đổi các bit thứ 6 (32) từ một 1-0 hoặc từ 0 đến 1.
Tất cả các ký tự ASCII là 32 từ các đối tác của chúng (ASCII là một thiết kế khéo léo vì điều này. Vì 32 là sức mạnh của 2 (2^5), thật dễ dàng để chuyển bit. Để có được giá trị ASCII của một bức thư, sử dụng được xây dựng trong chức năng PHP ord()
:
ord('a') // 65
ord('A') // 97
// 97 - 65 = 32
Vì vậy, bạn lặp qua chuỗi sử dụng strlen()
như phần giữa của for
vòng lặp, và nó sẽ lặp chính xác số lần khi chuỗi của bạn có chữ cái. Nếu ký tự ở vị trí $i
là một chữ cái (a-z (65-90) hoặc A-Z (97-122)), ký tự sẽ hoán đổi ký tự đó cho chữ hoa hoặc chữ thường bằng bitmask.
Sau đây là cách bitmask hoạt động:
0100 0001 // 65 (lowercase a)
0010 0000 // 32 (bitmask of 32)
--------- // XOR means: we put a 1 if the bits are different, a 0 if they are same.
0110 0001 // 97 (uppercase A)
Chúng ta có thể đảo ngược nó:
0110 0001 // 97 (A)
0010 0000 // Bitmask of 32
---------
0100 0001 // 65 (a)
Không cần str_replace
hoặc preg_replace
, chúng tôi chỉ trao đổi bit để thêm hoặc trừ đi 32 từ giá trị ASCII của nhân vật và chúng tôi trao đổi các trường hợp. Bit thứ 6 (thứ 6 từ bên phải) xác định nếu ký tự là chữ hoa hay chữ thường. Nếu đó là 0, đó là chữ thường và 1 nếu chữ hoa. Thay đổi bit từ 0 thành 1 quảng cáo 32, nhận giá trị hoa chr()
và thay đổi từ 1 thành 0 bằng trừ 32, chuyển chữ thường viết hoa.
swapCase('userId'); // USERiD
swapCase('USERiD'); // userId
swapCase('rot13'); // ROT13
Chúng tôi cũng có thể có một chức năng mà giao dịch hoán đổi các trường hợp trên một nhân vật đặc biệt:
// $i = position in string
function swapCaseAtChar($string, $i) {
$char = ord($string{$i});
if (($char > 64 && $char < 91) || ($char > 96 && $char < 123)) {
$string{$i} = chr($char^32);
return $string;
} else {
return $string;
}
}
echo swapCaseAtChar('iiiiiiii', 0); // Iiiiiiii
echo swapCaseAtChar('userid', 4); // userId
// Numbers are no issue
echo swapCaseAtChar('12345qqq', 7); // 12345qqQ
Bất kỳ ý tưởng làm thế nào để kiểm tra các trường hợp của một chuỗi? – tarnfeld
Điều này có thể chỉ hoạt động đối với các ký tự ASCII. Thay thế cho 'strotolower()' có thể là 'mb_strtolower()'. – Messa
'ctype_lower()' http://php.net/manual/en/function.ctype-lower.php –