How to find repeated array value when the key is always unique? - php
Array
(
[02-i-said-i-m-naruto.mp3] => 99
[018 APNE - TERE SANG.mp3] => 110
[04-sapana.mp3] => 133
[04 Kurnu Kuraunu.MP3] => 220
[005LAD~1.MP3] => 221
[04-akon-troublemaker_ft._sweet_rush - Copy.mp3] => 237
[04--somebodys_me.mp3] => 240
[01-school_of_rock_-_school_of_rock-xxl.mp3] => 253
[007. The Black Eyed Peas - Imma Be.mp3] => 257
[04 Timi Hau.mp3] => 266
[04-jennifer_lopez-(what_is)_love_(produced_by_dmile).mp3] => 267
[04-LIL~1.mp3] => 275
[034.Simple Plan - Perfect.mp3] => 278
[04 THE REAL SLIM SHADY.MP3] => 287
[007 thoda sa pyar hua hai(01).mp3] => 293
[02-pearl_jam-even_flow.mp3] => 294
[04-TUM~yuvraj.mp3] => 337
[01 - MTV Unplugged - Arjit Singh - Dua [DJMaza].mp3] => 339
[015 METRO - Alvida.mp3] => 341
[03 - Sabbra Cadabra.mp3] => 380
[04 - Sabbra Cadabra.mp3] => 380
[03 - The Unforgiven II.mp3] => 396
[04 - The Unforgiven II.mp3] => 396
)
This is the array that my current php processor generate (that generates the value in ascending order using asort()). Now I need to find the duplicate songs by song duration. Forexample, 03 - Sabbra Cadabra.mp3 is duplicate there. duplicate's duration is 380 seconds. I want something that would count number of 380 in the array values or bold the repeated key in regard of values. I tried to use array_count_values($arr) but that didnt help.
Warning: array_count_values() [function.array-count-values]: Can only count STRING and INTEGER values! in index.php on line 23
Try parsing the array values in a foreach loop.
$last= '';
$match_array = array();
foreach ( $array_name as $key => $value )
{
if($value == $last) {
$match_array[] = $value;
}
$last= $value;
{
$match_array should give you the duplicate entries.
I think array_unique and array_diff_assoc are much better options.
Following code will give you those array which are having duplicate time values:
$array = array
(
'02-i-said-i-m-naruto.mp3' => 99,
'018 APNE - TERE SANG.mp3' => 110,
'04-sapana.mp3' => 133,
'04 Kurnu Kuraunu.MP3' => 220,
'005LAD~1.MP3' => 221,
'04-akon-troublemaker_ft._sweet_rush - Copy.mp3' => 237,
'04--somebodys_me.mp3' => 240,
'01-school_of_rock_-_school_of_rock-xxl.mp3' => 253,
'007. The Black Eyed Peas - Imma Be.mp3' => 257,
'04 Timi Hau.mp3' => 266,
'04-jennifer_lopez-(what_is)_love_(produced_by_dmile).mp3' => 267,
'04-LIL~1.mp3' => 275,
'034.Simple Plan - Perfect.mp3' => 278,
'04 THE REAL SLIM SHADY.MP3' => 287,
'007 thoda sa pyar hua hai(01).mp3' => 293,
'02-pearl_jam-even_flow.mp3' => 294,
'04-TUM~yuvraj.mp3' => 337,
'01 - MTV Unplugged - Arjit Singh - Dua [DJMaza].mp3' => 339,
'015 METRO - Alvida.mp3' => 341,
'03 - Sabbra Cadabra.mp3' => 380,
'04 - Sabbra Cadabra.mp3' => 380,
'03 - The Unforgiven II.mp3' => 396,
'04 - The Unforgiven II.mp3' => 396,
);
$arrayUnique = array_unique($array);
print_r(array_diff_assoc($array, $arrayUnique));
Will give:
Array
(
[04 - Sabbra Cadabra.mp3] => 380
[04 - The Unforgiven II.mp3] => 396
)
Eliminate the two first lines and add your array var as $array if you want.
$dump = "array ( '02-i-said-i-m-naruto.mp3' => '99', '018 APNE - TERE SANG.mp3' => '110', '04-sapana.mp3' => '133', '04 Kurnu Kuraunu.MP3' => '220', '005LAD~1.MP3' => '221', '04-akon-troublemaker_ft._sweet_rush - Copy.mp3' => '237', '04--somebodys_me.mp3' => '240', '01-school_of_rock_-_school_of_rock-xxl.mp3' => '253', '007. The Black Eyed Peas - Imma Be.mp3' => '257', '04 Timi Hau.mp3' => '266', '04-jennifer_lopez-(what_is)_love_(produced_by_dmile).mp3' => '267', '04-LIL~1.mp3' => '275', '034.Simple Plan - Perfect.mp3' => '278', '04 THE REAL SLIM SHADY.MP3' => '287', '007 thoda sa pyar hua hai(01).mp3' => '293', '02-pearl_jam-even_flow.mp3' => '294', '04-TUM~yuvraj.mp3' => '337', '01 - MTV Unplugged - Arjit Singh - Dua [DJMaza].mp3' => '339', '015 METRO - Alvida.mp3' => '341', '03 - Sabbra Cadabra.mp3' => '380', '04 - Sabbra Cadabra.mp3' => '380', '03 - The Unforgiven II.mp3' => '396', '04 - The Unforgiven II.mp3' => '396', )";
eval("\$array=$dump;");
$array1 = array_count_values($array);
print_r(array_filter($array1, "duplicate"));
function duplicate($var) {
return $var > 1;
}
Related
PHP - Count number of values in a specific index of multidimensional array
I have a multidimensional array where I need to get the count of similar values in a specific index and create a new array with the results. I am using PHP 7.3. For example, I need to count the number of similar values in index [3] . Desired results MUFA-D = 2, BRD-IS = 3, JBC-BAK-B = 1. [0] => Array ( [0] => CHICAGO [1] => 14 [2] => MUFFIN A LINE [3] => MUFA-D [4] => Arm Bearings - Check for play, lubricate if needed. ) [1] => Array ( [0] => CHICAGO [1] => 14 [2] => MUFFIN A LINE [3] => MUFA-D [4] => Linkage - Check for wear and broken links. ) [2] => Array ( [0] => MEMPHIS [1] => 05 [2] => BREADING LINE 1 [3] => BRD1-IS [4] => Gear Box oil level ) [3] => Array ( [0] => MEMPHIS [1] => 05 [2] => BREADING LINE 1 [3] => BRD1-IS [4] => Bearings visual inspection ) [4] => Array ( [0] => MEMPHIS [1] => 05 [2] => BREADING LINE 1 [3] => BRD1-IS [4] => Electrical Plug condition ) [5] => Array ( [0] => CHICAGO [1] => 02 [2] => JBC LINE 2 [3] => JBC-BAK-B [4] => Plate separator shaft ) )
Using a couple of useful builtin functions you can do $in = [ ['CHICAGO', '14', 'MUFFIN A LINE', 'MUFA-D', 'Arm Bearings - Check for play, lubricate if needed.'], ['CHICAGO', '14', 'MUFFIN A LINE', 'MUFA-D', 'Linkage - Check for wear and broken links.'], ['MEMPHIS', '05', 'BREADING LINE 1', 'BRD1-IS', 'Gear Box oil level'], ['MEMPHIS', '05', 'BREADING LINE 1', 'BRD1-IS', 'Bearings visual inspection'], ['MEMPHIS', '05', 'BREADING LINE 1', 'BRD1-IS', 'Electrical Plug condition'], ['CHICAGO', '02', 'JBC LINE 2', 'JBC-BAK-B', 'Plate separator shaft'] ]; function grab3($occ) { return $occ[3]; } print_r(array_count_values(array_map('grab3', $in))); And the result is an array where the values are now the key of an array and the value is the count Array ( [MUFA-D] => 2 [BRD1-IS] => 3 [JBC-BAK-B] => 1 )
You can just loop over the array and use the indexes value as a key in an associative array to count. Then $result will contain your desired results. $data = [ ['CHICAGO', '14', 'MUFFIN A LINE', 'MUFA-D', 'Arm Bearings - Check for play, lubricate if needed.',], ['CHICAGO', '14', 'MUFFIN A LINE', 'MUFA-D', 'Linkage - Check for wear and broken links.',], ['MEMPHIS', '05', 'BREADING LINE 1', 'BRD1 - IS', 'Gear Box oil level',], ['MEMPHIS', '05', 'BREADING LINE 1', 'BRD1 - IS', 'Bearings visual inspection',], ['MEMPHIS', '05', 'BREADING LINE 1', 'BRD1 - IS', 'Electrical Plug condition',], ['CHICAGO', '02', 'JBC LINE 2', 'JBC - BAK - B', 'Plate separator shaft',], ]; $result = []; foreach ($data as $item) { $index = $item[3]; $result[$index] = isset($result[$index]) ? $result[$index] + 1 : 1; } print_r($result); Will print Array ( [MUFA-D] => 3 [BRD1 - IS] => 4 [JBC - BAK - B] => 2 )
You could use this function on your condition. function countSimilarValuesByIndex(array $MyArray,int $Index){ $SimilarValues = []; foreach($MyArray as $Object){ $SimilarValues[$Object[$Index]] = (isset($SimilarValues[$Object[$Index]]))? ++$SimilarValues[$Object[$Index]]:1; } return $SimilarValues; } $MyArray = [ ['CHICAGO', 14, 'MUFFIN A LINE', 'MUFA-D', 'Arm Bearings - Check for play, lubricate if needed.'], ['CHICAGO', 14, 'MUFFIN A LINE', 'MUFA-D', 'Linkage - Check for wear and broken links.'], ['MEMPHIS', 05, 'BREADING LINE 1', 'BRD1-IS', 'Gear Box oil level'], ['MEMPHIS', 05, 'BREADING LINE 1', 'BRD1-IS', 'Bearings visual inspection'], ['MEMPHIS', 05, 'BREADING LINE 1', 'BRD1-IS', 'Electrical Plug condition'], ['CHICAGO', 02, 'JBC LINE 2', 'JBC-BAK-B', 'Plate separator shaft'] ]; $Index = 1; $YourResult = countSimilarValuesByIndex($MyArray,$Index); Result: [ [14] => 2, [5] => 3, [2] => 1 ]
How to add sum values of array according to keys in php
I have an array of php like this Array ( [0] => Array ( [Sr_No] => 1 [Asan_Category] => Warm-Up [Asan_Cat_Val] => 8 [Asan_Sub_Category] => Ankle [Asan_Sub_Cat_Val] => 35 [Asan_Name] => General Ankle Warm up [Asan_Name_Val] => 447 [Prescribed_Steps] => 40 [Prescribed_Ratio] => 00 [Actual_Steps] => 12 [Actual_Ratio] => 0 ) [1] => Array ( [Sr_No] => 2 [Asan_Category] => Warm-Up [Asan_Cat_Val] => 8 [Asan_Sub_Category] => Knee [Asan_Sub_Cat_Val] => 111 [Asan_Name] => General knee warm up [Asan_Name_Val] => 464 [Prescribed_Steps] => 20 [Prescribed_Ratio] => 00 [Actual_Steps] => 14 [Actual_Ratio] => 0 ) [2] => Array ( [Sr_No] => 1 [Asan_Category] => Warm-Up [Asan_Cat_Val] => 8 [Asan_Sub_Category] => Ankle [Asan_Sub_Cat_Val] => 35 [Asan_Name] => General Ankle Warm up [Asan_Name_Val] => 447 [Prescribed_Steps] => 40 [Prescribed_Ratio] => 00 [Actual_Steps] => 10 [Actual_Ratio] => 0 ) [3] => Array ( [Sr_No] => 2 [Asan_Category] => Warm-Up [Asan_Cat_Val] => 8 [Asan_Sub_Category] => Knee [Asan_Sub_Cat_Val] => 111 [Asan_Name] => General knee warm up [Asan_Name_Val] => 464 [Prescribed_Steps] => 20 [Prescribed_Ratio] => 00 [Actual_Steps] => 9 [Actual_Ratio] => 0 ) ) The desired output I want Array ( [0] => Array ( [Asan_Id] => 447 [Asan_Category] => Warm-Up [Asan_Sub_Category] => Ankle [Asan_Name] => General Ankle Warm up [Prescribed_Steps] => 40 [Prescribed_Ratio] => 00 [Total_Steps] => 22 ) [1] => Array ( [Asan_Id] => 464 [Asan_Category] => Warm-Up [Asan_Sub_Category] => Knee [Asan_Name] => General knee warm up [Prescribed_Steps] => 20 [Prescribed_Ratio] => 00 [Total_Steps] => 23 ) ) I want those data who are repeating become one but their different actual steps become total steps with their sum. Please help me because I have tried some code but did not success like this $asan=[]; $total_steps=0; foreach ($aasan_details as $key) { $total_steps += $key['Actual_Steps']; if(!in_array($key['Asan_Name_Val'],$asan)) { $asan[] = $key['Asan_Name_Val']; $lookup[] = array("Asan_Id"=>$key['Asan_Name_Val'], "Asan_Category"=>$key['Asan_Category'], "Asan_Sub_Category"=>$key['Asan_Sub_Category'], "Asan_Name"=>$key['Asan_Name'], "Prescribed_Steps"=>$key['Prescribed_Steps'], "Prescribed_Ratio"=>$key['Prescribed_Ratio'], 'Total_Steps'=>$total_steps); } } It is not working , what should I do guys , please help me out where $aasan_details is the array which I showed above and the in lookup array I am getting uniqe values but not getting their total
The best solution would be to move this into a database and use a query to perform that exact operation for you. But if you have to do it in code, you could use a keyed array to basically group them up by however many fields need to match for them to be conjoined: e.g. foreach .. $consolidated[$item['Asan_Cat_Val']][$item['Asan_Sub_Cat_Val']][] = $item; Then make a couple of nested loops to go across this and sum everything up.
There a few useful techniques to explain here... You can reduce eye-strain in your looped array declarations by establishing a collection of keys that you know you want to retain in (copy to) the output array. This spares you having to type out each $keyName => $row[$keyName], like this (but ultimately make yourself happy). Declare temporary associative keys (using $id) while building your output array to allow isset() to make super fast checks for a pre-existing group. If a group is not yet set, then store the data with the new keys along with the data with the original keys. No arithmetic is necessary. The + symbols in my snippet are not "addition operators", they are "array union operators" -- they are merging the three arrays without a function call (otherwise array_merge() would do the same). When finished iterating the array, you may choose to re-index the result (remove the temporary associative keys) by calling array_values(). If you are not bothered by the existence of these temporary keys, you can omit the function call. If a group has been encountered before, you only need to modify the Total_steps. Use an addition-assignment operator (+=) for the briefest syntax. Code: (Demo) $keysToKeep = array_flip(['Asan_Category', 'Asan_Sub_Category', 'Asan_Name', 'Prescribed_Steps', 'Prescribed_Ratio']); foreach ($array as $row) { $id = $row['Asan_Name_Val']; if (!isset($result[$id])) { $result[$id] = ['Asan_Id' => $id] + array_intersect_key($row, $keysToKeep) + ['Total_Steps' => $row['Actual_Steps']]; } else { $result[$id]['Total_Steps'] += $row['Actual_Steps']; } } var_export(array_values($result)); Output: array ( 0 => array ( 'Asan_Id' => '447', 'Asan_Category' => 'Warm-Up', 'Asan_Sub_Category' => 'Ankle', 'Asan_Name' => 'General Ankle Warm up', 'Prescribed_Steps' => '40', 'Prescribed_Ratio' => '00', 'Total_Steps' => 22, ), 1 => array ( 'Asan_Id' => '464', 'Asan_Category' => 'Warm-Up', 'Asan_Sub_Category' => 'Knee', 'Asan_Name' => 'General knee warm up', 'Prescribed_Steps' => '20', 'Prescribed_Ratio' => '00', 'Total_Steps' => 23, ), )
Properly getting the sorting order of this array in PHP
I have a 2-dimensional array which the values... 9999999999999999 3201 4584 4821 1628 1218 1786 4738 4897 3122 9999999999999999 1400 1638 1797 2756 3323 5310 5472 4523 1400 9999999999999999 237 3198 4156 4723 6711 6872 4760 1638 237 9999999999999999 3435 4394 4961 6948 7110 1324 1846 3247 3485 9999999999999999 958 1525 3931 4093 932 2854 4273 4510 1002 9999999999999999 567 4873 5034 1499 3422 4840 5078 1569 567 9999999999999999 5440 5602 5061 5359 6760 6998 4019 4959 5526 9999999999999999 161 5233 5531 6931 7169 4190 5130 5697 171 9999999999999999 Here's the same array in code: array:9 [ 0 => array:9 [ 0 => 9999999999999999 1 => 3122 2 => 4523 3 => 4760 4 => 1324 5 => 932 6 => 1499 7 => 5061 8 => 5233 ] 1 => array:9 [ 0 => 3201 1 => 9999999999999999 2 => 1400 3 => 1638 4 => 1846 5 => 2854 6 => 3422 7 => 5359 8 => 5531 ] 2 => array:9 [ 0 => 4584 1 => 1400 2 => 9999999999999999 3 => 237 4 => 3247 5 => 4273 6 => 4840 7 => 6760 8 => 6931 ] 3 => array:9 [ 0 => 4821 1 => 1638 2 => 237 3 => 9999999999999999 4 => 3485 5 => 4510 6 => 5078 7 => 6998 8 => 7169 ] 4 => array:9 [ 0 => 1628 1 => 1797 2 => 3198 3 => 3435 4 => 9999999999999999 5 => 1002 6 => 1569 7 => 4019 8 => 4190 ] 5 => array:9 [ 0 => 1218 1 => 2756 2 => 4156 3 => 4394 4 => 958 5 => 9999999999999999 6 => 567 7 => 4959 8 => 5130 ] 6 => array:9 [ 0 => 1786 1 => 3323 2 => 4723 3 => 4961 4 => 1525 5 => 567 6 => 9999999999999999 7 => 5526 8 => 5697 ] 7 => array:9 [ 0 => 4738 1 => 5310 2 => 6711 3 => 6948 4 => 3931 5 => 4873 6 => 5440 7 => 9999999999999999 8 => 171 ] 8 => array:9 [ 0 => 4897 1 => 5472 2 => 6872 3 => 7110 4 => 4093 5 => 5034 6 => 5602 7 => 161 8 => 9999999999999999 ] ] What I'm trying to achieve is find the sorting order of this array in terms of closest. Each row contains the distance of a place to another place. In other words, the array looks something like: China India USA Japan China 0 50 4000 2000 India 50 0 4100 2100 USA 4050 4120 2 3000 Japan 2010 1950 2997 0 As you can see, the value to self is 0, sometimes it's a small number like 2-10 (not really sure thou) because Google distance matrix API sometimes returns big values for same origin and destination too which is why I replaced it to 9999999999999999 throughout the diagonal in my original array above. The goal is to get the sorting in terms of distance. The first entry is the starting point so in the case of the hypothetical array above it would be: [0 1 3 2] i.e. From China to India, then India to Japan, and Japan to the USA. My goal is to use array_multisort, in the end, to order just the keys with the place names so that it's ordered properly. The code I came up with isn't working as I hoped for: $order = [0]; $i = 0; $nextItemToProcessIndex = 0; foreach($tempMatrix as $key => $entry) { $tempMatrix[$key][$key] = PHP_INT_MAX; } while(!empty($tempMatrix)) { $closestItemIndex = array_search(min($tempMatrix[$nextItemToProcessIndex]), $tempMatrix[$nextItemToProcessIndex]); array_push($order, $closestItemIndex); $this->pull_item($tempMatrix, $nextItemToProcessIndex); $nextItemToProcessIndex = $closestItemIndex - 1; $i++; } dd($order); ... ... public function pull_item(&$array, $offset) { array_walk($array, function (&$v) use ($offset) { array_splice($v, $offset, 1); }); $row = array_splice($array, $offset, 1); return $row; }
If altering matrix column labels is ok for you - you can do sorting like that: $dist = [ "China" => ['China' => 0, 'India' => 50, 'USA' => 4000, 'Japan' => 2000], "India" => ['China' => 50, 'India' => 0, 'USA' => 4100, 'Japan' => 2100], "USA " => ['China' => 4050, 'India' => 4120, 'USA' => 2, 'Japan' => 3000], "Japan" => ['China' => 2010, 'India' => 1950, 'USA' => 2997, 'Japan' => 0] ]; // sort columns by distance foreach ($dist as $key => $value) { asort($dist[$key]); } // display distances matrix foreach ($dist as $row_c => $data) { $row1 = "\t"; $row2 = $row_c . " : "; foreach ($data as $col_c => $col_dist) { $row1 .= $col_c . "\t"; $row2 .= $col_dist . "\t"; } echo "{$row1}\n{$row2}\n\n"; } Outputs: China India Japan USA China : 0 50 2000 4000 India China Japan USA India : 0 50 2100 4100 USA Japan China India USA : 2 3000 4050 4120 Japan India China USA Japan : 0 1950 2010 2997
I was able to figure out a solution to this on my own. Posting here if anyone else comes across the same issue: $nextItemToProcess = 0; $order = [0]; foreach(range(0, count($tempMatrix) - 2) as $i) { if(count(array_diff_key($tempMatrix[$nextItemToProcess], $order)) == 1) { $order = array_merge($order, array_diff(range(0, count($tempMatrix)-1), $order)); break; } $diffArray = array_diff_key($tempMatrix[$nextItemToProcess], array_flip($order)); $closestItemIndex = array_search(min($diffArray), $tempMatrix[$nextItemToProcess]); array_push($order, $closestItemIndex); $nextItemToProcess = $closestItemIndex; } $ascOrigins = []; foreach($order as $i) { array_push($ascOrigins, $arrOrigins[$i]); } ascOrigins is the array in ascending order of place distances. I thought I could use php's array_multisort but it wasn't useful since here I'm sorting the keys of arr based on the values of order. (I know an array_flip could have done the trick but this works fine).
How to get array value then implode them into new array in PHP
I have an array: Array ( [10 - 20] => 3 [20 - 30] => 43 [30 - 40] => 5 [40 - 50] => 1 [50 - 60] => 0 [60 - 70] => 0 ) I want to make new array that will send via json. Now I have result in json like this(thanks for guys below who answered my question): {"success":true,"data":["3","43","5","1","0","0"]} I need json to be {"success":true,"data":[3,43,5,1,0,0]}, cause only with that format data show in line chart of highchart Sorry for my stupid questionThank You
Update Here's how you can get your response... $values = array ( '10 - 20' => 3, '20 - 30' => 43, '30 - 40' => 5, '40 - 50' => 1, '50 - 60' => 0, '60 - 70' => 0, ); $data = array_values($values); $response = array('sucess' => true, 'data' => $data); echo json_encode($response); Use array_values, this can be done like so: $values = array ( '10 - 20' => 3, '20 - 30' => 43, '30 - 40' => 5, '40 - 50' => 1, '50 - 60' => 0, '60 - 70' => 0, ); $values = array_values($values); $data = json_encode($values); echo data; Output: [3,43,5,1,0,0]
You might be new to php, Declaration of associative array should be like below $arr=array( '[10 - 20]' => 3, '[20 - 30]' => 43, '[30 - 40]' => 5, '[40 - 50]' => 1, '[50 - 60]' => 0, '[60 - 70]' => 0 ); array('Key'=>value,'key2'=> value); Write forearch/for/ any loop to get the values, This is useful if you want to extract both key and values at the same time foreach ($arr as $key=>$value) { echo "$value <br>"; } If you want to get only values then use array_values($arr)
You need to use array_values. PHP Array $arr = array("10 - 20" => 3, "20 - 30" => 43, "30 - 40" => 5, "40 - 50" => 1, "50 - 60" => 0, "60 - 70" => 0 ); Array values from the array. $arr2 = array_values($arr); print_r($arr2); Output Array Array ( [0] => 3 [1] => 43 [2] => 5 [3] => 1 [4] => 0 [5] => 0 ) If you need only the values as string then use implode. echo implode(" , ", $arr2); Result 3 , 43 , 5 , 1 , 0 , 0
PHP: Convert unicode codepoint to UTF-8
I have my data in this format: U+597D or like this U+6211. I want to convert them to UTF-8 (original characters are 好 and 我). How can I do it?
$utf8string = html_entity_decode(preg_replace("/U\+([0-9A-F]{4})/", "&#x\\1;", $string), ENT_NOQUOTES, 'UTF-8'); is probably the simplest solution.
function utf8($num) { if($num<=0x7F) return chr($num); if($num<=0x7FF) return chr(($num>>6)+192).chr(($num&63)+128); if($num<=0xFFFF) return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128); if($num<=0x1FFFFF) return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128).chr(($num&63)+128); return ''; } function uniord($c) { $ord0 = ord($c{0}); if ($ord0>=0 && $ord0<=127) return $ord0; $ord1 = ord($c{1}); if ($ord0>=192 && $ord0<=223) return ($ord0-192)*64 + ($ord1-128); $ord2 = ord($c{2}); if ($ord0>=224 && $ord0<=239) return ($ord0-224)*4096 + ($ord1-128)*64 + ($ord2-128); $ord3 = ord($c{3}); if ($ord0>=240 && $ord0<=247) return ($ord0-240)*262144 + ($ord1-128)*4096 + ($ord2-128)*64 + ($ord3-128); return false; } utf8() and uniord() try to mirror the chr() and ord() functions on php: echo utf8(0x6211)."\n"; echo uniord(utf8(0x6211))."\n"; echo "U+".dechex(uniord(utf8(0x6211)))."\n"; //In your case: $wo='U+6211'; $hao='U+597D'; echo utf8(hexdec(str_replace("U+","", $wo)))."\n"; echo utf8(hexdec(str_replace("U+","", $hao)))."\n"; output: 我 25105 U+6211 我 好
PHP 7+ As of PHP 7, you can use the Unicode codepoint escape syntax to do this. echo "\u{597D}"; outputs 好.
I just wrote a polyfill for missing multibyte versions of ord and chr with the following in mind: It defines functions mb_ord and mb_chr only if they don't already exist. If they do exist in your framework or some future version of PHP, the polyfill will be ignored. It uses the widely used mbstring extension to do the conversion. If the mbstring extension is not loaded, it will use the iconv extension instead. I also added functions for HTMLentities encoding / decoding and encoding / decoding to JSON format as well as some demo code for how to use these functions Code if (!function_exists('codepoint_encode')) { function codepoint_encode($str) { return substr(json_encode($str), 1, -1); } } if (!function_exists('codepoint_decode')) { function codepoint_decode($str) { return json_decode(sprintf('"%s"', $str)); } } if (!function_exists('mb_internal_encoding')) { function mb_internal_encoding($encoding = NULL) { return ($from_encoding === NULL) ? iconv_get_encoding() : iconv_set_encoding($encoding); } } if (!function_exists('mb_convert_encoding')) { function mb_convert_encoding($str, $to_encoding, $from_encoding = NULL) { return iconv(($from_encoding === NULL) ? mb_internal_encoding() : $from_encoding, $to_encoding, $str); } } if (!function_exists('mb_chr')) { function mb_chr($ord, $encoding = 'UTF-8') { if ($encoding === 'UCS-4BE') { return pack("N", $ord); } else { return mb_convert_encoding(mb_chr($ord, 'UCS-4BE'), $encoding, 'UCS-4BE'); } } } if (!function_exists('mb_ord')) { function mb_ord($char, $encoding = 'UTF-8') { if ($encoding === 'UCS-4BE') { list(, $ord) = (strlen($char) === 4) ? #unpack('N', $char) : #unpack('n', $char); return $ord; } else { return mb_ord(mb_convert_encoding($char, 'UCS-4BE', $encoding), 'UCS-4BE'); } } } if (!function_exists('mb_htmlentities')) { function mb_htmlentities($string, $hex = true, $encoding = 'UTF-8') { return preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function ($match) use ($hex) { return sprintf($hex ? '&#x%X;' : '&#%d;', mb_ord($match[0])); }, $string); } } if (!function_exists('mb_html_entity_decode')) { function mb_html_entity_decode($string, $flags = null, $encoding = 'UTF-8') { return html_entity_decode($string, ($flags === NULL) ? ENT_COMPAT | ENT_HTML401 : $flags, $encoding); } } How to use echo "\nGet string from numeric DEC value\n"; var_dump(mb_chr(25105)); var_dump(mb_chr(22909)); echo "\nGet string from numeric HEX value\n"; var_dump(mb_chr(0x6211)); var_dump(mb_chr(0x597D)); echo "\nGet numeric value of character as DEC int\n"; var_dump(mb_ord('我')); var_dump(mb_ord('好')); echo "\nGet numeric value of character as HEX string\n"; var_dump(dechex(mb_ord('我'))); var_dump(dechex(mb_ord('好'))); echo "\nEncode / decode to DEC based HTML entities\n"; var_dump(mb_htmlentities('我好', false)); var_dump(mb_html_entity_decode('我好')); echo "\nEncode / decode to HEX based HTML entities\n"; var_dump(mb_htmlentities('我好')); var_dump(mb_html_entity_decode('我好')); echo "\nUse JSON encoding / decoding\n"; var_dump(codepoint_encode("我好")); var_dump(codepoint_decode('\u6211\u597d')); Output Get string from numeric DEC value string(3) "我" string(3) "好" Get string from numeric HEX value string(3) "我" string(3) "好" Get numeric value of character as DEC string int(25105) int(22909) Get numeric value of character as HEX string string(4) "6211" string(4) "597d" Encode / decode to DEC based HTML entities string(16) "我好" string(6) "我好" Encode / decode to HEX based HTML entities string(16) "我好" string(6) "我好" Use JSON encoding / decoding string(12) "\u6211\u597d" string(6) "我好"
mb_convert_encoding( preg_replace("/U\+([0-9A-F]*)/" ,"&#x\\1;" ,'U+597DU+6211' ) ,"UTF-8" ,"HTML-ENTITIES" ); works fine, too.
<?php function chr_utf8($n,$f='C*'){ return $n<(1<<7)?chr($n):($n<1<<11?pack($f,192|$n>>6,1<<7|191&$n): ($n<(1<<16)?pack($f,224|$n>>12,1<<7|63&$n>>6,1<<7|63&$n): ($n<(1<<20|1<<16)?pack($f,240|$n>>18,1<<7|63&$n>>12,1<<7|63&$n>>6,1<<7|63&$n):''))); } $your_input='U+597D'; echo (chr_utf8(hexdec(ltrim($your_input,'U+')))); // Output 好 If you want to use a callback function you can try it : <?php // Note: function chr_utf8 shown above is required $your_input='U+597DU+6211'; $result=preg_replace_callback('#U\+([a-f0-9]+)#i',function($a){return chr_utf8(hexdec($a[1]));},$your_input); echo $result; // Output 好我 Check it in https://eval.in/748187
I was in the position I needed to filter specific characters without affecting the html because I was using a wysiwig editor, but people copy pasting from word would add some nice unrenderable characters to the content. My solution boils down to simple replacement lists. class ReplaceIllegal { public static $find = array ( 0 => '\x0', 1 => '\x1', 2 => '\x2', 3 => '\x3', 4 => '\x4', 5 => '\x5', 6 => '\x6', 7 => '\x7', 8 => '\x8', 9 => '\x9', 10 => '\xA', 11 => '\xB', 12 => '\xC', 13 => '\xD', 14 => '\xE', 15 => '\xF', 16 => '\x10', 17 => '\x11', 18 => '\x12', 19 => '\x13', 20 => '\x14', 21 => '\x15', 22 => '\x16', 23 => '\x17', 24 => '\x18', 25 => '\x19', 26 => '\x1A', 27 => '\x1B', 28 => '\x1C', 29 => '\x1D', 30 => '\x1E', 31 => '\x80', 32 => '\x81', 33 => '\x82', 34 => '\x83', 35 => '\x84', 36 => '\x85', 37 => '\x86', 38 => '\x87', 39 => '\x88', 40 => '\x89', 41 => '\x8A', 42 => '\x8B', 43 => '\x8C', 44 => '\x8D', 45 => '\x8E', 46 => '\x8F', 47 => '\x90', 48 => '\x91', 49 => '\x92', 50 => '\x93', 51 => '\x94', 52 => '\x95', 53 => '\x96', 54 => '\x97', 55 => '\x98', 56 => '\x99', 57 => '\x9A', 58 => '\x9B', 59 => '\x9C', 60 => '\x9D', 61 => '\x9E', 62 => '\x9F', 63 => '\xA0', 64 => '\xA1', 65 => '\xA2', 66 => '\xA3', 67 => '\xA4', 68 => '\xA5', 69 => '\xA6', 70 => '\xA7', 71 => '\xA8', 72 => '\xA9', 73 => '\xAA', 74 => '\xAB', 75 => '\xAC', 76 => '\xAD', 77 => '\xAE', 78 => '\xAF', 79 => '\xB0', 80 => '\xB1', 81 => '\xB2', 82 => '\xB3', 83 => '\xB4', 84 => '\xB5', 85 => '\xB6', 86 => '\xB7', 87 => '\xB8', 88 => '\xB9', 89 => '\xBA', 90 => '\xBB', 91 => '\xBC', 92 => '\xBD', 93 => '\xBE', 94 => '\xBF', 95 => '\xC0', 96 => '\xC1', 97 => '\xC2', 98 => '\xC3', 99 => '\xC4', 100 => '\xC5', 101 => '\xC6', 102 => '\xC7', 103 => '\xC8', 104 => '\xC9', 105 => '\xCA', 106 => '\xCB', 107 => '\xCC', 108 => '\xCD', 109 => '\xCE', 110 => '\xCF', 111 => '\xD0', 112 => '\xD1', 113 => '\xD2', 114 => '\xD3', 115 => '\xD4', 116 => '\xD5', 117 => '\xD6', 118 => '\xD7', 119 => '\xD8', 120 => '\xD9', 121 => '\xDA', 122 => '\xDB', 123 => '\xDC', 124 => '\xDD', 125 => '\xDE', 126 => '\xDF', 127 => '\xE0', 128 => '\xE1', 129 => '\xE2', 130 => '\xE3', 131 => '\xE4', 132 => '\xE5', 133 => '\xE6', 134 => '\xE7', 135 => '\xE8', 136 => '\xE9', 137 => '\xEA', 138 => '\xEB', 139 => '\xEC', 140 => '\xED', 141 => '\xEE', 142 => '\xEF', 143 => '\xF0', 144 => '\xF1', 145 => '\xF2', 146 => '\xF3', 147 => '\xF4', 148 => '\xF5', 149 => '\xF6', 150 => '\xF7', 151 => '\xF8', 152 => '\xF9', 153 => '\xFA', 154 => '\xFB', 155 => '\xFC', 156 => '\xFD', 157 => '\xFE', ); private static $replace = array ( 0 => '', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => '', 7 => '', 8 => '', 9 => ' ', 10 => ' ', 11 => '', 12 => '', 13 => ' ', 14 => '', 15 => '', 16 => '', 17 => '', 18 => '', 19 => '', 20 => '', 21 => '', 22 => '', 23 => '', 24 => '', 25 => '', 26 => '', 27 => '', 28 => '', 29 => '', 30 => '', 31 => '', 32 => '', 33 => '', 34 => '', 35 => '', 36 => ' ', 37 => '', 38 => '', 39 => '', 40 => '', 41 => '', 42 => '', 43 => '', 44 => '', 45 => '', 46 => '', 47 => '', 48 => '', 49 => '', 50 => '', 51 => '', 52 => '', 53 => '', 54 => '', 55 => '', 56 => '', 57 => '', 58 => '', 59 => '', 60 => '', 61 => '', 62 => '', 63 => ' ', 64 => '¡', 65 => '¢', 66 => '£', 67 => '¤', 68 => '¥', 69 => '¦', 70 => '§', 71 => '¨', 72 => '©', 73 => 'ª', 74 => '«', 75 => '¬', 76 => '', 77 => '®', 78 => '¯', 79 => '°', 80 => '±', 81 => '²', 82 => '³', 83 => '´', 84 => 'µ', 85 => '¶', 86 => '·', 87 => '¸', 88 => '¹', 89 => 'º', 90 => '»', 91 => '¼', 92 => '½', 93 => '¾', 94 => '¿', 95 => 'À', 96 => 'Á', 97 => 'Â', 98 => 'Ã', 99 => 'Ä', 100 => 'Å', 101 => 'Æ', 102 => 'Ç', 103 => 'È', 104 => 'É', 105 => 'Ê', 106 => 'Ë', 107 => 'Ì', 108 => 'Í', 109 => 'Î', 110 => 'Ï', 111 => 'Ð', 112 => 'Ñ', 113 => 'Ò', 114 => 'Ó', 115 => 'Ô', 116 => 'Õ', 117 => 'Ö', 118 => '×', 119 => 'Ø', 120 => 'Ù', 121 => 'Ú', 122 => 'Û', 123 => 'Ü', 124 => 'Ý', 125 => 'Þ', 126 => 'ß', 127 => 'à', 128 => 'á', 129 => 'â', 130 => 'ã', 131 => 'ä', 132 => 'å', 133 => 'æ', 134 => 'ç', 135 => 'è', 136 => 'é', 137 => 'ê', 138 => 'ë', 139 => 'ì', 140 => 'í', 141 => 'î', 142 => 'ï', 143 => 'ð', 144 => 'ñ', 145 => 'ò', 146 => 'ó', 147 => 'ô', 148 => 'õ', 149 => 'ö', 150 => '÷', 151 => 'ø', 152 => 'ù', 153 => 'ú', 154 => 'û', 155 => 'ü', 156 => 'ý', 157 => 'þ', ); /* * replace illegal characters for escaped html character but don't touch anything else. */ public static function getSaveValue($value) { return str_replace(self::$find, self::$replace, $value); } public static function makeIllegal($find,$replace) { self::$find[] = $find; self::$replace[] = $replace; } }
This worked fine for me. If you have a string "Letters u00e1 u00e9 etc." replace by "Letters á é". function unicode2html($str){ // Set the locale to something that's UTF-8 capable setlocale(LC_ALL, 'en_US.UTF-8'); // Convert the codepoints to entities $str = preg_replace("/u([0-9a-fA-F]{4})/", "&#x\\1;", $str); // Convert the entities to a UTF-8 string return iconv("UTF-8", "ISO-8859-1//TRANSLIT", $str); }
With the aid of the following table: http://en.wikipedia.org/wiki/UTF-8#Description can't be simpler :) Simply mask the unicode numbers according to which range they fit in.