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.
Related
This question already has answers here:
How to remove an array value from another array using PHP question
(3 answers)
Closed 2 years ago.
I tried the following code and it should be working, but not getting the required result. What's wrong with the code? I have two arrays and I want to remove the common elements in both arrays so I wore the following code.
<?php
$aMgaMembersList= array (
0 => '9194962',
1 => '9197448',
2 => '9174039',
3 => '9199473',
4 => '9175598',
5 => '9197474',
6 => '9195444',
7 => '9195268',
8 => '9189438',
9 => '9175103',
10 => '9199619',
11 => '9195267',
12 => '9194463',
13 => '9196333',
14 => '9197471',
15 => '9198479',
16 => '9197472',
17 => '9185479',
18 => '9197452',
19 => '9197442',
20 => '9180861',
21 => '9194950',
22 => '9198464',
23 => '9199613',
24 => '9175939',
25 => '9195442',
26 => '9190203',
27 => '9199613',
) ;
$aRocketMembersList = array (
0 => '9174039',
1 => '9175103',
2 => '9175598',
3 => '9175939',
4 => '9180861',
5 => '9185479',
6 => '9189438',
7 => '9190203',
8 => '9194463',
9 => '9194950',
10 => '9194962',
11 => '9195267',
12 => '9195268',
13 => '9195442',
14 => '9195444',
15 => '9196333',
16 => '9197442',
17 => '9197448',
18 => '9197452',
19 => '9197471',
20 => '9197472',
21 => '9197474',
22 => '9198464',
23 => '9198479',
24 => '9199473',
25 => '9199613',
26 => '9199619',
27 => 'arun',
) ;
if (is_array($aRocketMembersList)) {
foreach ($aRocketMembersList as $rocketUsername) {
if (in_array($rocketUsername, $aMgaMembersList)) {
unset($aMgaMembersList[array_search($rocketUsername, $aMgaMembersList)]);
unset($aRocketMembersList[array_search($rocketUsername, $aRocketMembersList)]);
}
}
}
print_r($aRocketMembersList);
print_r($aMgaMembersList);
The out put is
Array
(
[27] => arun
)
Array
(
[27] => 9199613
)
The element 9199613 shouldn't be there. Why it's happening? I ran the code in a different environment and the result is same.
Here's a different function that works regardless of the order of Arrays:
<?php
function different($array1, $array2){
$m = array_merge($array1, $array2); $x = array_intersect($array1, $array2); $a = array_diff($m, $x); $b = array_diff($x, $m); $a = array_merge($a, $b);
$r = [];
foreach($a as $v){
$o = new StdClass; $k = array_search($v, $array1);
if($k === false)$k = array_search($v, $array2);
$o->$k = [$array1[$k], $array2[$k]]; $r[] = $o;
}
return $r;
}
$aMgaMembersList = [
0 => '9194962',
1 => '9197448',
2 => '9174039',
3 => '9199473',
4 => '9175598',
5 => '9197474',
6 => '9195444',
7 => '9195268',
8 => '9189438',
9 => '9175103',
10 => '9199619',
11 => '9195267',
12 => '9194463',
13 => '9196333',
14 => '9197471',
15 => '9198479',
16 => '9197472',
17 => '9185479',
18 => '9197452',
19 => '9197442',
20 => '9180861',
21 => '9194950',
22 => '9198464',
23 => '9199613',
24 => '9175939',
25 => '9195442',
26 => '9190203',
27 => '9199613'
];
$aRocketMembersList = [
0 => '9174039',
1 => '9175103',
2 => '9175598',
3 => '9175939',
4 => '9180861',
5 => '9185479',
6 => '9189438',
7 => '9190203',
8 => '9194463',
9 => '9194950',
10 => '9194962',
11 => '9195267',
12 => '9195268',
13 => '9195442',
14 => '9195444',
15 => '9196333',
16 => '9197442',
17 => '9197448',
18 => '9197452',
19 => '9197471',
20 => '9197472',
21 => '9197474',
22 => '9198464',
23 => '9198479',
24 => '9199473',
25 => '9199613',
26 => '9199619',
27 => 'arun'
];
$diffArray = different($aMgaMembersList, $aRocketMembersList);
$test = json_encode($diffArray);
?>
$tmp1 = array_diff($aMgaMembersList,$aRocketMembersList);
$tmp2 = array_diff($aRocketMembersList,$aMgaMembersList);
$final = array_unqiue(array_merge($tmp1, $tmp2));
unset($tmp1);unset($tmp2);//and maybe original arrays?
There are probably better solutions, but that should work for you. If you had associative arrays instead of numeric values you could exclude array_unqiue
EDIT:
I originally assumed you wanted the results in one array, if that's unnecessary just use the array_diff function twice, and you can maintain your original array names as desired. Again there are probably better solutions (more memory/processor efficient), but in most practical cases this will be fine. If you're working with extremely large data sets... do more research ;)
I have to display result as
दुई खर्ब सतासी अर्ब अन्ठान्नब्बे करोड नब्बे लाख बाह्र हजार तीन सय पचहत्तर ...
It displays result correctly till five numbers..
But it doesn't display as needed when we use six numbers....
like 111111 .... It displays "एक सय एघार हजार एक सय एघार"
Where as it must be as "एक लाख एघार हजार एक सय एघार" .....
In case of seven and more numbers it throws error....
error 'Undefined offset: 1000000 in.....' ...
<?php
function convert_number_to_words($number) {
$hyphen = '-';
$conjunction = ' ';
$separator = ' ';
$negative = 'negative ';
$decimal = ' point ';
$dictionary = 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 => 'सय',
1000 => 'हजार',
100000 => 'लाख',
10000000 => 'करोड',
1000000000 => 'अर्ब',
100000000000 => 'खर्ब'
);
if (!is_numeric($number)) {
return false;
}
if (($number >= 0 && (int) $number < 0) || (int) $number < 0 -
PHP_INT_MAX) {
trigger_error(
'convert_number_to_words only accepts numbers between -' .
PHP_INT_MAX . ' and ' . PHP_INT_MAX,
E_USER_WARNING
);
return false;
}
if ($number < 0) {
return $negative . convert_number_to_words(abs($number));
}
$string = $fraction = null;
if (strpos($number, '.') !== false) {
list($number, $fraction) = explode('.', $number);
}
switch (true) {
case $number < 100:
$string = $dictionary[$number];
break;
case $number < 100:
$tens = ((int) ($number / 10)) * 10;
$units = $number % 10;
$string = $dictionary[$tens];
if ($units) {
$string .= $hyphen . $dictionary[$units];
}
break;
case $number < 1000:
$hundreds = $number / 100;
$remainder = $number % 100;
$string = $dictionary[$hundreds] . ' ' . $dictionary[100];
if ($remainder) {
$string .= $conjunction . convert_number_to_words($remainder);
}
break;;
default:
$baseUnit = pow(100000, floor(log($number, 100000)));
$numBaseUnits = (int) ($number / $baseUnit);
$remainder = $number % $baseUnit;
$string = convert_number_to_words($numBaseUnits) . ' ' .
$dictionary[$baseUnit];
if ($remainder) {
$string .= $remainder < 100 ? $conjunction : $separator;
$string .= convert_number_to_words($remainder);
}
break;
}
if (null !== $fraction && is_numeric($fraction)) {
$string .= $decimal;
$words = array();
foreach (str_split((string) $fraction) as $number) {
$words[] = $dictionary[$number];
}
$string .= implode(' ', $words);
}
return $string;
}
?>
Page "numtoword.php"
Page "index.php"
<?php
include('numword.php');
echo convert_number_to_words(287989012375);
?>
It looks like you are making it more difficult than it needs to be. I created a simpler recursive function, moved the dictionary and settings outside the function (generating a dictionary array on every function call was eating up a LOT of memory and is not necessary). I didn't include fractions but this should be a good starting point to expand off of:
<?php
$devnagriNumeralWords = [
'dictionary' => [
'smallUnits' => [
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 => 'उनान्सय'
],
'largeUnits' => [
100 => 'सय',
1000 => 'हजार',
100000 => 'लाख',
10000000 => 'करोड',
1000000000 => 'अर्ब',
100000000000 => 'खर्ब'
]
],
'hyphen' => '-',
'conjunction' => ' ',
'separator' => ' ',
'negative' => 'negative ',
'decimal' => ' point '
];
function convert_devnagri_number_to_words($number) {
global $devnagriNumeralWords;
$numLen = strlen($number);
$output = [ 'prefix' => '', 'base' => '', 'suffix' => '' ];
$base = pow(10, $numLen-1);
$smallestLargeUnit = array_keys($devnagriNumeralWords['dictionary']['largeUnits'])[0];
$isNegative = $number < 0;
if( $isNegative ) {
$output['prefix'] .= $devnagriNumeralWords['negative'];
$number = abs($number);
}
if( $number < $smallestLargeUnit ) {
// Number is less than 100
$prefix = $number;
} else {
// Get base amount (100, 1000, 100000, etc)
if( isset($devnagriNumeralWords['dictionary']['largeUnits'][$base]) ) {
$largeUnit = $devnagriNumeralWords['dictionary']['largeUnits'][$base];
} else {
// No exact large unit match, find next smallest
while( $base >= $smallestLargeUnit ) {
$base = (int) ($base / 10);
if( isset($devnagriNumeralWords['dictionary']['largeUnits'][$base]) ) {
break; // Found a match!
}
}
}
$output['base'] .= $devnagriNumeralWords['dictionary']['largeUnits'][$base];
// Get prefix, e.g. "28" when number is 28564
$prefix = (int) ($number / $base);
// Subtract prefix to get next part to process
// E.g. the next number is 345 when the number is 85345
$nextNumber = $number - ($prefix * $base);
if( $nextNumber > 0 )
$output['suffix'] = convert_devnagri_number_to_words($nextNumber);
}
if( $prefix >= 0 ) {
$output['prefix'] .= $devnagriNumeralWords['dictionary']['smallUnits'][$prefix];
}
// Put it all together!
return implode( $devnagriNumeralWords['separator'], array_filter($output) );
}
echo convert_devnagri_number_to_words(287989012375);
This is my string:
$string = "format,surcharge,amount,1,card,basicprice 3,50 F010F020,0%,3,50 ,,,";
and i want to have an array which should look like this:
array(
0 => "format",
1 => "surcharge",
2 => "amount",
3 => "1",
4 => "card",
5 => "basicprice",
6 => "3,50", //<-- tricky part, i complete don't get how i can solve this
7 => "card",
8 => "F010", //<-- tricky part, i complete don't get how i can solve this
9 => "F020", //<-- tricky part, i complete don't get how i can solve this
10 => "3,50",
);
so my tries look like this:
$string = "Format,Aufpreis,Anzahl,1,Card,Basispreis 3,50 F010F020,0%,3,50 ,,,,,,";
$regEx = '/,/';
$replace = ' ';
$perfectArray = preg_replace('/,/', $replace, $string2);
var_dump($perfectArray);
or like this
$array = str_split($string);
$from = array(",", '"');
$to = array(" ", " ");
foreach ($array as $value)
{
$value = str_replace($from, $to, $string);
}
var_dump($value);
someone know how i can solve this? especially the "tricky part" (i put a comment in the code)
would be very nice if someone can answer :)
As mentioned in your comments, if this is coming from csv try using
fgetcsv function.
You can directly work on these values.
Have a look at it here http://php.net/manual/en/function.fgetcsv.php, the example explains pretty well
After you mentioned in comments that you have raw data in CSV format, the use of regular expression is not the best solution.
Instead split the data into an array with PHP's CSV functions, like str_getcsv:
$csv = 'F251,43%,"3,50 €","0,50 €","0,50 €",,"0,50 €","0,50 €","0,50 €","0,49 €",
"0,49 €",,"0,47 €",,"0,47 €",,"0,46 €","0,46 €","0,44 €","0,44 €","0,44 €",,
"0,43 €",,"0,43 €","0,43 €",,,"0,41 €",,,"0,40 €","0,40 €",,"0,39 €",
"0,39 €",,"0,37 €","0,37 €","0,36 €","0,36 €","0,36 €","0,36 €","0,36 €"';
$data = str_getcsv($csv);
var_export ($data);
Output:
array (
0 => 'F251',
1 => '43%',
2 => '3,50 €',
3 => '0,50 €',
4 => '0,50 €',
5 => '',
6 => '0,50 €',
7 => '0,50 €',
8 => '0,50 €',
9 => '0,49 €',
10 => '0,49 €',
11 => '',
12 => '0,47 €',
13 => '',
14 => '0,47 €',
15 => '',
16 => '0,46 €',
17 => '0,46 €',
18 => '0,44 €',
19 => '0,44 €',
20 => '0,44 €',
21 => '',
22 => '0,43 €',
23 => '',
24 => '0,43 €',
25 => '0,43 €',
26 => '',
27 => '',
28 => '0,41 €',
29 => '',
30 => '',
31 => '0,40 €',
32 => '0,40 €',
33 => '',
34 => '0,39 €',
35 => '0,39 €',
36 => '',
37 => '0,37 €',
38 => '0,37 €',
39 => '0,36 €',
40 => '0,36 €',
41 => '0,36 €',
42 => '0,36 €',
43 => '0,36 €',
)
If you would like to get rid of the € and % signs, and/or use the decimal point for numbers (to allow further calculations in PHP), then you could do this:
$data = array_map(function ($v) {
// get rid of `€` or `%` at the end of values:
$v = preg_replace('/( €|%)$/', '', $v);
// if you want to replace the decimal comma to point for further calculations:
$num = str_replace(',', '.', str_replace('.', '', $v));
return is_numeric($num) ? $num : $v;
}, $data);
var_export ($data);
Which outputs:
array (
0 => 'F251',
1 => '43',
2 => '3.50',
3 => '0.50',
4 => '0.50',
5 => '',
6 => '0.50',
7 => '0.50',
8 => '0.50',
9 => '0.49',
10 => '0.49',
11 => '',
12 => '0.47',
13 => '',
14 => '0.47',
15 => '',
16 => '0.46',
17 => '0.46',
18 => '0.44',
19 => '0.44',
20 => '0.44',
21 => '',
22 => '0.43',
23 => '',
24 => '0.43',
25 => '0.43',
26 => '',
27 => '',
28 => '0.41',
29 => '',
30 => '',
31 => '0.40',
32 => '0.40',
33 => '',
34 => '0.39',
35 => '0.39',
36 => '',
37 => '0.37',
38 => '0.37',
39 => '0.36',
40 => '0.36',
41 => '0.36',
42 => '0.36',
43 => '0.36',
)
Original answer based on regular expressions
You could do this with a regular expression, but it depends on what your rules are for splitting other strings. This regular expression assumes the string will always have the same number of items in the same order, and concerning the F010 and F020 it assumes that these always each occupy exactly 4 characters and are always present:
$string = "format,surcharge,amount,1,card,basicprice 3,50 F010F020,0%,3,50 ,,,";
preg_match("/(.*?),(.*?),(.*?),(.*?),(.*?),(.*?)\s+(.*?)\s+(.{4})(.{4}),(.*?),(\d+,\d\d)\s/",
$string, $matches);
var_export ($matches);
This outputs:
array (
0 => 'format,surcharge,amount,1,card,basicprice 3,50 F010F020,0%,3,50 ',
1 => 'format',
2 => 'surcharge',
3 => 'amount',
4 => '1',
5 => 'card',
6 => 'basicprice',
7 => '3,50',
8 => 'F010',
9 => 'F020',
10 => '0%',
11 => '3,50',
)
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;
}
I wrote a FFT (Fast Fourier Transform) module for PHP recently. When I tried to test it, It always throws an error that the array $this->reverseTable has some index not defined. I got no clue of how to solve this problem.
Here's the PHP code:
<?php
class FourierTransform {
public $bufferSize;
public $sampleRate;
public $bandwidth;
public $spectrum = array();
public $real = array();
public $imag = array();
public $peakBand = 0;
public $peak = 0;
public function __construct($bufferSize,$sampleRate){
$this->bufferSize = $bufferSize;
$this->sampleRate = $sampleRate;
$this->bandwidth = 2 / $bufferSize * $sampleRate / 2;
}
public function getBandFrequency($index){
return $this->bandwidth * $index + $this->bandwidth / 2;
}
public function calculateSpectrum(){
$bSi = 2 / $this->bufferSize;
for($i = 0,$N = $this->bufferSize/2; $i < $N; $i++){
$rval = $this->real[$i];
$ival = $this->imag[$i];
$mag = $bSi * sqrt($rval * $rval + $ival * $ival);
if($mag > $this->peak){
$this->peakBand = $i;
$this->peak = $mag;
}
$this->spectrum[$i] = $mag;
}
}
}
class FFT extends FourierTransform {
public $reverseTable = array();
public $sinTable = array();
public $cosTable = array();
public function __construct($bufferSize,$sampleRate){
parent::__construct($bufferSize,$sampleRate);
$limit = 1;
$bit = $bufferSize >> 1;
while($limit < $bufferSize){
for($i = 0; $i < $limit; $i++){
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
}
$limit = $limit << 1;
$bit = $bit >> 1;
}
for($i = 0; $i < $bufferSize; $i++){
$this->sinTable[$i] = sin(-M_PI / $i);
$this->cosTable[$i] = cos(-M_PI / $i);
}
}
public function foward($buffer){
$k = floor(log($this->bufferSize,2));
if(pow(2,$k) !== $this->bufferSize) throw new Exception('Invalid buffer size, must be a power of 2.');
if($this->bufferSize !== count($buffer)) throw new Exception('Supplied buffer is not the same size as defined FFT.');
$halfSize = 1;
for($i = 0; $i < $this->bufferSize; $i++){
$this->real[$i] = $buffer[$this->reverseTable[$i]];
$this->imag[$i] = 0;
}
while($halfSize < $this->bufferSize){
$phaseShiftReal = $this->cosTable[$halfSize];
$phaseShiftImag = $this->sinTable[$halfSize];
$currentPhaseShiftReal = 1;
$currentPhaseShiftImag = 0;
for($fftStep = 0; $fftStep < $halfSize; $fftStep++){
while($fftStep < $this->bufferSize){
$off = $fftStep + $halfSize;
$tr = ($currentPhaseShiftReal * $this->real[$off]) - ($currentPhaseShiftImag * $this->imag[$off]);
$ti = ($currentPhaseShiftReal * $this->imag[$off]) + ($currentPhaseShiftImag * $this->real[$off]);
$this->real[$off] = $this->real[$fftStep] - $tr;
$this->imag[$off] = $this->imag[$fftStep] - $ti;
$this->real[$fftStep] += $tr;
$this->imag[$fftStep] += $ti;
$fftStep += $halfSize << 1;
}
$tmpReal = $currentPhaseShiftReal;
$currentPhaseShiftReal = ($tmpReal * $phaseShiftReal) - ($currentPhaseShiftImag * $phaseShiftImag);
$currentPhaseShiftImag = ($tmpReal * $phaseShiftImag) + ($currentPhaseShiftImag * $phaseShiftReal);
}
$halfSize = $halfSize << 1;
}
$this->calculateSpectrum();
}
}
?>
The test sample is a sine wave at 440Hz.
When I tried to run the code, it throws this error
Notice: Undefined offset: 0 in C:\Program Files
(x86)\EasyPHP-12.1\www\fft.php on line 48
continuously.
The array that has problem has data like this:
Array
(
[1] => 512
[2] => 256
[3] => 768
[4] => 128
[5] => 640
[6] => 384
[7] => 896
[8] => 64
[9] => 576
[10] => 320
[11] => 832
[12] => 192
[13] => 704
[14] => 448
[15] => 960
[16] => 32
[17] => 544
[18] => 288
[19] => 800
[20] => 160
[21] => 672
[22] => 416
[23] => 928
[24] => 96
[25] => 608
[26] => 352
[27] => 864
[28] => 224
[29] => 736
[30] => 480
[31] => 992
[32] => 16
[33] => 528
[34] => 272
[35] => 784
[36] => 144
[37] => 656
[38] => 400
[39] => 912
[40] => 80
[41] => 592
[42] => 336
[43] => 848
[44] => 208
[45] => 720
...
[978] => 303
[979] => 815
[980] => 175
[981] => 687
[982] => 431
[983] => 943
[984] => 111
[985] => 623
[986] => 367
[987] => 879
[988] => 239
[989] => 751
[990] => 495
[991] => 1007
[992] => 31
[993] => 543
[994] => 287
[995] => 799
[996] => 159
[997] => 671
[998] => 415
[999] => 927
[1000] => 95
[1001] => 607
[1002] => 351
[1003] => 863
[1004] => 223
[1005] => 735
[1006] => 479
[1007] => 991
[1008] => 63
[1009] => 575
[1010] => 319
[1011] => 831
[1012] => 191
[1013] => 703
[1014] => 447
[1015] => 959
[1016] => 127
[1017] => 639
[1018] => 383
[1019] => 895
[1020] => 255
[1021] => 767
[1022] => 511
[1023] => 1023
)
Edit: The previous problem is solved but now another problem is raised. At function forward() it throws an uncaught exception Invalid buffer size, must be a power of 2. Even if the buffer size is right.
Any help will be appreciated.
Assuming that this is the whole class, I presume that the issue lies on this line inside your FFT constructor:
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
From what I can tell you declare reverseTable as an array, but this line is the only place in the class where any elements are added to that array, so the fact that you're setting the reverseTable[$i+$limit] element using a never-defined reverseTable[$i] value is going to give you problems in the first first iteration of that while loop when it tries to use the undefined index $i (reverseTable[$i]). You'll have to give reverseTable[0] a value before you enter that loop.
Although you didn't provide where the line was, my guess is it has something to do with this line:
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
This is in your constructor, and this bit especially looks wrong $this->reverseTable[$i] + $bit;. You are asking for the value from the reverseTable array, but this key is not initialized anywhere in the constructor.
I am not sure how to fix this, as it is a logic error on your part.