token_get_all

dakata__92

Super Moderator
Как да преброя всички tokens в един файл и да изведа броят им в масив примерно:
[for] => 2,
[if] => 10

и така нататък.

PHP:
print_r(token_get_all(file_get_contents(__FILE__)));

Как да преброя всичките и да ги върня в масив като този?
 
PHP:
$a = array_combine($included = get_included_files(),array_map(function($callback){
	$tokens = token_get_all(file_get_contents($callback));
	$count = null;
	foreach($tokens as $token){
		if(is_numeric($token[0])){
			$count[] = token_name($token[0]);
		}
	}
	return array_count_values($count);
},$included));

print_r($a);
До тук добре. Така вадя за всеки един файл общият брой токени които има в него, но сега желая да е глобално за цялото приложение и директно да ги комбинира оке веднъш нещо подобно на array_count_values и да извади информацията за абсолятно всички файлове. Това вади като инфо в момента искам да го комбинирам така че да събера всичко и тоест да стане масив: [T_OPEN_TAG] = 3 и така нататък.
Код:
Array
(
    [C:\xampp\htdocs\DPH\public\index.php] => Array
        (
            [T_OPEN_TAG] => 1
            [T_STRING] => 18
            [T_CONSTANT_ENCAPSED_STRING] => 8
            [T_WHITESPACE] => 39
            [T_INCLUDE_ONCE] => 1
            [T_VARIABLE] => 15
            [T_NS_SEPARATOR] => 3
            [T_DOUBLE_COLON] => 1
            [T_ECHO] => 4
            [T_COMMENT] => 2
            [T_FUNCTION] => 1
            [T_FOREACH] => 1
            [T_AS] => 1
            [T_IF] => 1
            [T_LNUMBER] => 2
            [T_RETURN] => 1
        )

    [C:\xampp\htdocs\DPH\CCF\system\core\SAL.php] => Array
        (
            [T_OPEN_TAG] => 1
            [T_COMMENT] => 1
            [T_WHITESPACE] => 131
            [T_NAMESPACE] => 1
            [T_STRING] => 82
            [T_NS_SEPARATOR] => 22
            [T_VARIABLE] => 42
            [T_DIR] => 3
            [T_CONSTANT_ENCAPSED_STRING] => 14
            [T_IF] => 6
            [T_LOGICAL_AND] => 1
            [T_INCLUDE_ONCE] => 3
            [T_ELSE] => 1
            [T_EXIT] => 1
            [T_CLASS] => 1
            [T_PRIVATE] => 6
            [T_STATIC] => 2
            [T_FUNCTION] => 6
            [T_DOUBLE_COLON] => 9
            [T_OBJECT_OPERATOR] => 21
            [T_IS_EQUAL] => 3
            [T_PUBLIC] => 5
            [T_NEW] => 4
            [T_EMPTY] => 2
            [T_RETURN] => 6
        )

    [C:\xampp\htdocs\DPH\CCF\GlobalFile.php] => Array
        (
            [T_OPEN_TAG] => 1
            [T_WHITESPACE] => 129
            [T_COMMENT] => 13
            [T_STRING] => 44
            [T_CONSTANT_ENCAPSED_STRING] => 56
            [T_FUNCTION] => 4
            [T_VARIABLE] => 27
            [T_LNUMBER] => 2
            [T_ARRAY] => 6
            [T_RETURN] => 4
            [T_NEW] => 1
            [T_DOUBLE_ARROW] => 11
        )
 
Че то много просто...
PHP:
$arr = [];

// минаваш през всеки файл
foreach($a as $file)
    // за всеки файл обхождаш данните
    foreach($file as $key => $val)
         // ако още не е записана дадената стойност, ѝ даваш стойност $val - стойността за текущия файл
         if(empty($arr[$key]))
             $arr[$key] = (int) $val;
         // ако вече е записана дадената стойност, добавяш към нея текущата
         else
             $arr[$key] += $val;
 
anonimen каза:
Че то много просто...
PHP:
$arr = [];

// минаваш през всеки файл
foreach($a as $file)
    // за всеки файл обхождаш данните
    foreach($file as $key => $val)
         // ако още не е записана дадената стойност, ѝ даваш стойност $val - стойността за текущия файл
         if(empty($arr[$key]))
             $arr[$key] = (int) $val;
         // ако вече е записана дадената стойност, добавяш към нея текущата
         else
             $arr[$key] += $val;

Опитвам се да го направя с array_map, ще ми помогнеш ли?
 
Същият въпрос: http://stackoverflow.com/questions/1496682/how-to-sum-values-of-the-array-of-the-same-key

PHP:
$sumResult = array_map("sum", $rArray[0], $rArray[1], $rArray[2]);

function sum($arr1, $arr2, $arr3)
{
    return($arr1+$arr2+$arr3);
}

Само че ти не знаеш колко елемента ще има $rArray[], затова може би ще ти трябва нещо по-такова:

PHP:
$args = $arr_with_files;
array_unshift($args, 'array_sum');
// в момента $args съдържа нещо като ['array_sum', [/*всичко от 1-вия файл*/], [/*всичко от 2-рия файл*/], ...]

// извикваш array_map с горните аргументи
$result = call_user_func_array("array_map", $args);

Изобщо не съм сигурен дали ще тръгне, пробвай :?:
 
Впрочем да попитам според теб кое е по-бързо? Foreach или array_map ? Правил съм преди време тест и не открих особена разлика в скоростта въпреки че map беше по-бърз. По форумите правят винаги различни заключения кой е по-бърз.
 
dakata__92 каза:
Впрочем да попитам според теб кое е по-бързо? Foreach или array_map ? Правил съм преди време тест и не открих особена разлика в скоростта въпреки че map беше по-бърз. По форумите правят винаги различни заключения кой е по-бърз.
array map по-бърз? Как бе.. :idea:
странно...

Но виж това:
http://stackoverflow.com/questions/18144782/performance-of-foreach-array-map-with-lambda-and-array-map-with-static-function

Foreach: 0.7 sec
Map on closure: 3.4 sec
Map on function name: 1.2 sec.

Но като гледам на последния човек с array map му е било по-бързо...
 
anonimen каза:
dakata__92 каза:
Впрочем да попитам според теб кое е по-бързо? Foreach или array_map ? Правил съм преди време тест и не открих особена разлика в скоростта въпреки че map беше по-бърз. По форумите правят винаги различни заключения кой е по-бърз.
array map по-бърз? Как бе.. :idea:
странно...

Но виж това:
http://stackoverflow.com/questions/18144782/performance-of-foreach-array-map-with-lambda-and-array-map-with-static-function

Foreach: 0.7 sec
Map on closure: 3.4 sec
Map on function name: 1.2 sec.

Но като гледам на последния човек с array map му е било по-бързо...
Странно но факт е че при мен преди доста време беше по-бързо.
http://stackoverflow.com/questions/8395909/array-map-vs-loop-and-operation
Не си спомням примера но отгоре също има обяснения в тази насока. Странно е но май така се получава.
 
Доколкото разбирам array_map е написана на C, поради което се изпълнява по-бързо от foreach, който първо трябва да се интерпретира и после да се изпълни...

И тъй като това е доста по-кратко от foreach-а (като количество код), според мен можеш съвсем спокойно да си го ползваш:

PHP:
array_unshift($arr, 'array_sum');
$result = call_user_func_array("array_map", $arr);

все пак си направи един тест, виж кое как върви и дай резултата :idea:

// п.п. само че горното ще промени $arr като добави "array_sum" в началото, така че може би ще е по-добре да го направиш в отделна променлива.
// п.п.2 даже няма нужда и от това, можеш директно да го направиш така:

PHP:
array_unshift($arr, 'array_sum');
$arr = call_user_func_array("array_map", $arr);
 
anonimen каза:
Доколкото разбирам array_map е написана на C, поради което се изпълнява по-бързо от foreach, който първо трябва да се интерпретира и после да се изпълни...

И тъй като това е доста по-кратко от foreach-а (като количество код), според мен можеш съвсем спокойно да си го ползваш:

PHP:
array_unshift($arr, 'array_sum');
$result = call_user_func_array("array_map", $arr);

все пак си направи един тест, виж кое как върви и дай резултата :idea:
Пробвам кода ето така и ми се иска да го сбия така, че когато извикам $a направо да ми вади този масив който вади сега така с твоят код.
PHP:
$a = array_combine($included = get_included_files(),array_map(function($callback){
	$tokens = token_get_all(file_get_contents($callback));
	$count = null;
	foreach($tokens as $token){
		if(is_numeric($token[0])){
			$count[] = token_name($token[0]);
		}
	}
	return array_count_values($count);
},$included));

$arr = [];

// минаваш през всеки файл
foreach($a as $file){
    // за всеки файл обхождаш данните
    foreach($file as $key => $val){
         // ако още не е записана дадената стойност, ѝ даваш стойност $val - стойността за текущия файл
         if(empty($arr[$key]))
             $arr[$key] = (int) $val;
         // ако вече е записана дадената стойност, добавяш към нея текущата
         else
             $arr[$key] += $val;
	}
}
arsort($arr);
print_r($arr);
 
Редактирах по-горе, направи го така:

PHP:
array_unshift($a, 'array_sum');
$a = call_user_func_array("array_map", $a);

точно преди

$arr=[]

и махаш всичко надолу до arsort() print_r()
 
anonimen каза:
Редактирах по-горе, направи го така:

PHP:
array_unshift($a, 'array_sum');
$a = call_user_func_array("array_map", $a);

точно преди

$arr=[]

и махаш всичко надолу до arsort() print_r()
Foreach e по-бърз!
PHP:
$a = range(1,10000);
$start = microtime(true);
$r = array_map(function($n){
    return($n * $n * $n);
}
,$a);
$end = microtime(true) - $start;
echo "$end<br>";

$start = microtime(true);
$r = null;
foreach($a as $n){
	$r[] = $n * $n * $n;
}
$end = microtime(true) - $start;
echo "$end<br>";
 
Това добре ли е ?
PHP:
$tokens = function(array $files){
	$count = array();
	foreach($files as $file){
		$allTokens = token_get_all(file_get_contents($file));
        foreach($allTokens as $token){
            if(is_numeric($token[0])){
                $count[] = token_name($token[0]);
            }
        }
	}
	arsort($count);
	return array_count_values($count);
};
print_r($tokens(get_included_files()));
 
Естествено, че е по-бърз. Едното е оператор, другото функция. Оставям за домашно да разберете каква е разликата м/у двете.
Хинт: Преди да се извика функцията в стека трябва да се "спасят" регистрите на процесора, адреса за връщане, да се пушнат формалните параметри на функцията а след нейното приклюване - всичко по обратният ред. Когато функцията е в цикъл и самата тя вика друга функция става още по-забавно.
Поздрави.
 
imagination каза:
Естествено, че е по-бърз. Едното е оператор, другото функция. Оставям за домашно да разберете каква е разликата м/у двете.
Хинт: Преди да се извика функцията в стека трябва да се "спасят" регистрите на процесора, адреса за връщане, да се пушнат формалните параметри на функцията а след нейното приклюване - всичко по обратният ред. Когато функцията е в цикъл и самата тя вика друга функция става още по-забавно.
Поздрави.
Да но преди време получих обратният резултат. Както и в нета се чете има доста хора които са получили този резултат. Реално ще си ползвам loop foreach защото само с един вложен цикъл в друг се получи повече от бързо четимо и удобно за ползване.
 
imagination каза:
Естествено, че е по-бърз. Едното е оператор, другото функция. Оставям за домашно да разберете каква е разликата м/у двете.
Хинт: Преди да се извика функцията в стека трябва да се "спасят" регистрите на процесора, адреса за връщане, да се пушнат формалните параметри на функцията а след нейното приклюване - всичко по обратният ред. Когато функцията е в цикъл и самата тя вика друга функция става още по-забавно.
Поздрави.
Съгласен съм, въпреки че по-горе писах обратното :roll:

Само че едно не ми е ясно - при положение, че има доста по-бързи имплементации на дадените функции, защо изобщо съществуват? Не говоря конкретно за array_map, а и за всички останали - array_sum да речем.
Какъв е смисълът на една вградена функция, ако може да се напише със сравнително малък код като това например:

PHP:
$res = 0;
foreach($arr as $n) $res += $n;

Защо? :!:
 
Въпроса е защо трябва да е по-бавна от това което си написъл ти. Не съм мерил кое колко памет заема не съм правил такъв бенчмарк но май след време ще си драсна един хубав тестер.
 
Предполагам отговорът е доста комплексен.
За един код не е най-важното да е бърз. Трябва и да е четим и да не заема много памет. Функциите пестят памет. Не може всичко да е "инлайн" кодирано.
В крайна сметка се търси баланс м/у използвана памет и скорост - параметри, които обикновенно са в обратна пропорционалност.
За четимосттана кода вече писах. този фореацх след 2 седмици ще има да го гледаш и да се чудиш защо е там.
В крайна сметка производителността на едно приложение не се определя само от кода а и от външните фактори, като бази от данни и външни ресурси ако се ползват такива. Аз лично най-много проблеми съм имам с бавни бази от данни, код (от към бързодействие) досега не ми се е налагало да оптимизирам, но заявки - почти всеки ден. Паметта също доста често не стига по споделените хостинги.
 
По въпроса за паметта/бързодействието, тук проведохме една дискусийка, която не засяга конкрето vinsgb а по принцип този "вид" ситуации:
http://web-tourist.net/forum/viewtopic.php?t=128107
Така и не стигнахме до единодушие, тъй като всички отговори имаха предимства и недостатъци, и ако искаш да погледнеш предполагам ще е полезно за всички :?:

Моята идея - http://web-tourist.net/forum/viewtopic.php?p=664265#664265 трябваше да се доближи възможно най-много до бързодействието и същевременно да пази паметта на скрипта, като същевременно пък заема повече памет на сървъра.
За сметка това пък от гледната точка на юзера не е много удобно...
 

Back
Горе