Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Неправильная работа функции arsort
 
 автор: dump   (15.09.2009 в 15:13)   письмо автору
 
 

В отладчике я проверил значение массива до сортировки функцией, было:

$output:array =
"www.scienceblog.ru" :object =
0 = "275"
"www.dxdt.ru" :object =
0 = "150"
"www.cultureblog.ru" :object =
0 = "0"
"www.liverss.ru" :object =
0 = "250"
"www.skuffelse.ru" :object =
0 = "10"
"www.internet.ru" :object =
0 = "2400"
"www.voliadis.ru" :object =
0 = "10"
"www.niopasd.ru" :object =
0 = "0"
"www.infuture.ru" :object =
0 = "600"



а стало после сортировки:

$output:array =
"www.voliadis.ru" :object =
0 = "10"
"www.niopasd.ru" :object =
0 = "0"
"www.infuture.ru" :object =
0 = "600"
"www.internet.ru" :object =
0 = "2400"
"www.skuffelse.ru" :object =
0 = "10"
"www.dxdt.ru" :object =
0 = "150"
"www.cultureblog.ru" :object =
0 = "0"
"www.liverss.ru" :object =
0 = "250"
"www.scienceblog.ru" :object =
0 = "275"
т.е. не отсортировался по убыванию, а хаотично. Тоже самое и с функцией asort. Кто-нибудь знает почему?

  Ответить  
 
 автор: Trianon   (15.09.2009 в 15:26)   письмо автору
 
   для: dump   (15.09.2009 в 15:13)
 

у Вас там вроде объекты лежат. Эти объекты сравниваются на больше/меньше?

  Ответить  
 
 автор: dump   (15.09.2009 в 16:38)   письмо автору
 
   для: Trianon   (15.09.2009 в 15:26)
 

Ну да, на больше меньше. Но ведь я сравниваю значения

  Ответить  
 
 автор: cheops   (15.09.2009 в 16:59)   письмо автору
 
   для: dump   (15.09.2009 в 16:38)
 

Скорее всего для корректно работы вам придется задать логику сравнения объектов при помощи функции обратного вызова и использовать uksort() и uasort().

  Ответить  
 
 автор: dump   (15.09.2009 в 17:49)   письмо автору
 
   для: cheops   (15.09.2009 в 16:59)
 

Да, попробовал, но ничего не получается. Объекты не удаётся сравнить как числа. Может быть у кого был опыт сравнения массивов, значениями которых были объекты?

  Ответить  
 
 автор: cheops   (15.09.2009 в 17:51)   письмо автору
 
   для: dump   (15.09.2009 в 17:49)
 

Так вы сравниваете не объекты, а члены объектов. Собственно функции обратного вызова как раз предназначены для сложных объектов и массивов.

  Ответить  
 
 автор: dump   (15.09.2009 в 18:00)   письмо автору
 
   для: cheops   (15.09.2009 в 17:51)
 

Ну я правда не совсем хорошо разбираюсь с функциями обратного вызова. Было бы очень интересно посмотреть на манул именно по сравнению членов объектов, если таковой конечно имеется.

  Ответить  
 
 автор: cheops   (15.09.2009 в 18:04)   письмо автору
 
   для: dump   (15.09.2009 в 18:00)
 

Обычно примерно так поступают
<?php
  
class obj {
    public 
$value;

    function 
__construct($val)
    {
      
$this->value $val;
    }
  }
  function 
cmp($a$b
  {
    if (
$a->value == $b->value) {
        return 
0;
    }
    return (
$a->value $b->value) ? -1;
  }

  
$arr[] = new obj(10);
  
$arr[] = new obj(4);
  
$arr[] = new obj(2);
  
$arr[] = new obj(4);
  
$arr[] = new obj(5);

  
usort($arr"cmp");

  foreach (
$arr as $object) {
    echo 
$object->value."<br>";
  }
?> 

  Ответить  
 
 автор: dump   (15.09.2009 в 18:31)   письмо автору
 
   для: cheops   (15.09.2009 в 18:04)
 

Ну я попробовал внедрить это в свой скрипт, но результат тот же:
Исходный массив:
[$output:array =
"www.scienceblog.ru" :object =
0 = "275"
"www.dxdt.ru" :object =
0 = "150"
"www.cultureblog.ru" :object =
0 = "0"
"www.liverss.ru" :object =
0 = "250"
"www.skuffelse.ru" :object =
0 = "10"
"www.internet.ru" :object =
0 = "2400"
"www.voliadis.ru" :object =
0 = "10"
"www.niopasd.ru" :object =
0 = "0"
"www.infuture.ru" :object =
0 = "600"


Внедрённый код:

function cmp($a, $b)
{
if ($a->value == $b->value) {
return 0;
}
return ($a->value > $b->value) ? -1 : 1;
}
usort($output, "cmp");


Массив после обработки:

$output:array =
0 :object =
0 = "0"
1 :object =
0 = "150"
2 :object =
0 = "2400"
3 :object =
0 = "0"
4 :object =
0 = "275"
5 :object =
0 = "250"
6 :object =
0 = "10"
7 :object =
0 = "10"
8 :object =
0 = "600"

  Ответить  
 
 автор: cheops   (15.09.2009 в 18:35)   письмо автору
 
   для: dump   (15.09.2009 в 18:31)
 

У вас числа где-то в строки превращаются, попробуйте заменить строку
if ($a->value == $b->value)

на
if ((int)$a->value == (int)$b->value)

  Ответить  
 
 автор: dump   (15.09.2009 в 18:38)   письмо автору
 
   для: cheops   (15.09.2009 в 18:35)
 

Я заменил и то же самое

  Ответить  
 
 автор: cheops   (15.09.2009 в 18:43)   письмо автору
 
   для: dump   (15.09.2009 в 18:38)
 

У вас объект сложный? Просто если мы не сможем воспроизвести ситуацию, то вряд ли можно будет продолжить отладку - явное приведение типа должно разрешать ситуацию - если это не происходит - нужен массив которым вы манипулируете, чтобы дальше смотреть, как его обуздать.

  Ответить  
 
 автор: dump   (15.09.2009 в 18:44)   письмо автору
 
   для: dump   (15.09.2009 в 18:38)
 

Хотя почему (int)?А может intaval?

  Ответить  
 
 автор: dump   (15.09.2009 в 18:45)   письмо автору
 
   для: dump   (15.09.2009 в 18:44)
 

Да собственно вот сам скрипт:

<?php
set_time_limit(0);
function get_yandex($url){

$ret = 'N/A';

if( substr($url,0,7) != 'http://' )
$url = 'http://' . $url;

if( $content = get_download('http://bar-navig.yandex.ru/u?ver=2&url='. urlencode($url) .'&show=1&post=0') ){

if( class_exists('SimpleXMLElement') ){
if( $xmldoc = new SimpleXMLElement($content) ){
$tcy = $xmldoc->tcy;
if( !empty($tcy) ){
$ret = $tcy['value'];
}
}
}
else{
preg_match("/value=\"(.\d*)\"/",$content,$tic);
if( !empty($tic[1]) ) $ret = $tic[1];
}
}

return $ret;

}

function get_download($url){

$ret = false;

if( function_exists('curl_init') ){
if( $curl = curl_init() ){

if( !curl_setopt($curl,CURLOPT_URL,$url) ) return $ret;
if( !curl_setopt($curl,CURLOPT_RETURNTRANSFER,true) ) return $ret;
if( !curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,30) ) return $ret;
if( !curl_setopt($curl,CURLOPT_HEADER,false) ) return $ret;
if( !curl_setopt($curl,CURLOPT_ENCODING,"gzip,deflate") ) return $ret;

$ret = curl_exec($curl);

curl_close($curl);
}
}
else{
$u = parse_url($url);

if( $fp = @fsockopen($u['host'],!empty($u['port']) ? $u['port'] : 80 ) ){

$headers = 'GET '. $u['path'] . '?' . $u['query'] .' HTTP/1.0'. "\r\n";
$headers .= 'Host: '. $u['host'] ."\r\n";
$headers .= 'Connection: Close' . "\r\n\r\n";

fwrite($fp, $headers);
$ret = '';

while( !feof($fp) ){
$ret .= fgets($fp,1024);
}

$ret = substr($ret,strpos($ret,"\r\n\r\n") + 4);

fclose($fp);
}
}

return $ret;
}
if (empty($_POST['urls']))
echo
<<<HTML_FORM
<center>
Input urls
<form method=POST>
<textarea name='urls' cols=100 rows=10 wrap="off" ></textarea><br>
<input type='submit' value='Prepare'>
</form>
<center>
HTML_FORM;
else
{
$input=explode("\r\n",$_POST['urls']);
for ($i=0;$i<=count($input)-2;$i++)
{
$url=parse_url($input[$i],PHP_URL_HOST);
if (strpos($url,'.ru'))
switch (strpos($url,'ww.'))
{
case TRUE:
if (substr_count($url,'.')==2) $output[$url]=get_yandex($url);
break;
case FALSE:
if (substr_count($url,'.')==1) $output['www.'.$url]=get_yandex($url);
break;
}
//$dump=$output[$url]+2;
}
function cmp($a, $b)
{
if ((int)$a->value == (int)$b->value){
return 0;
}
return ($a->value > $b->value) ? -1 : 1;
}
usort($output, "cmp");
//function FCmp($previous,$real)
//{
//if ($previous<=$real) return TRUE; else return FALSE;
//}
//uasort($output,"FCmp");
//arsort($output);
/*foreach ($output as $index=>$value) //echo "$index - $value<br>";
{
if ($output[$index]<=$output[$previous_index]) $sorted_output[
$previous_index=$index;
}
*/
}
?>





Простой сортировщик ссылок по тицу

  Ответить  
 
 автор: cheops   (15.09.2009 в 18:46)   письмо автору
 
   для: dump   (15.09.2009 в 18:44)
 

(int) допускается, но можно попробвать intval(), это пожалуй даже лучше.

  Ответить  
 
 автор: cheops   (15.09.2009 в 18:50)   письмо автору
 
   для: cheops   (15.09.2009 в 18:46)
 

А вот в чем дело, мы с вами забыли тип привести ещё и в этой строке
return ($a->value > $b->value) ? -1 : 1;

  Ответить  
 
 автор: dump   (15.09.2009 в 18:54)   письмо автору
 
   для: cheops   (15.09.2009 в 18:50)
 

Если я вас правильно понимаю, то можно сделать так:

function cmp($a, $b)
{
if (intval($a)->value == intval($b)->value){
return 0;
}
return (intaval($a)->value > intaval($b)->value) ? -1 : 1;
}
usort($output, "cmp");

  Ответить  
 
 автор: cheops   (15.09.2009 в 18:56)   письмо автору
 
   для: dump   (15.09.2009 в 18:54)
 

Не совсем, скорее так
<?php
function cmp($a$b)
{
if (
intval($a->value) == intval($b->value)){
return 
0;
}
return (
intval($a->value) > intval($b->value)) ? -1;
}
usort($output"cmp");
?>

Обратите так же внимание на ошибку в написании intval() в вашем пример.

  Ответить  
 
 автор: dump   (15.09.2009 в 19:01)   письмо автору
 
   для: cheops   (15.09.2009 в 18:56)
 

Да, я попробовал ваш код, но массив не сортируется.....

  Ответить  
 
 автор: cheops   (15.09.2009 в 19:06)   письмо автору
 
   для: dump   (15.09.2009 в 19:01)
 

1) Попробуйте использовать uasort() вместо usort() - вам ведь нужно сохранить связь ключей?
2) Что нужно вбить в тектовую область, чтобы запустить скрипт?

  Ответить  
 
 автор: dump   (15.09.2009 в 19:07)   письмо автору
 
   для: dump   (15.09.2009 в 19:01)
 

Может стоит применить какой-нибудь другой алгоритм сортировки такого массива? Существует ли для этого уже готовые решения?

  Ответить  
 
 автор: cheops   (15.09.2009 в 19:11)   письмо автору
 
   для: dump   (15.09.2009 в 19:07)
 

Не понятно вот что - откуда у вас объекты берутся и почему бы просто не воспользоваться ассоциативным массивом, для которого можно применить готовые функции asort() и arsort()?

  Ответить  
 
 автор: dump   (15.09.2009 в 19:14)   письмо автору
 
   для: cheops   (15.09.2009 в 19:11)
 

Дело в том , что я вынужден пользоваться функцией, которая возвращает объекты.

Вот она:

function get_yandex($url){

$ret = 'N/A';

if( substr($url,0,7) != 'http://' )
$url = 'http://' . $url;

if( $content = get_download('http://bar-navig.yandex.ru/u?ver=2&url='. urlencode($url) .'&show=1&post=0') ){

if( class_exists('SimpleXMLElement') ){
if( $xmldoc = new SimpleXMLElement($content) ){
$tcy = $xmldoc->tcy;
if( !empty($tcy) ){
$ret = $tcy['value'];
}
}
}
else{
preg_match("/value=\"(.\d*)\"/",$content,$tic);
if( !empty($tic[1]) ) $ret = $tic[1];
}
}

return $ret;

}

  Ответить  
 
 автор: cheops   (15.09.2009 в 19:17)   письмо автору
 
   для: dump   (15.09.2009 в 19:14)
 

Хорошо, как можно запустить ваш скрипт - какие домены нужно вбить в текстовую область?

  Ответить  
 
 автор: dump   (15.09.2009 в 19:31)   письмо автору
 
   для: cheops   (15.09.2009 в 19:17)
 

Да вот я вставлял этот список:

http://scienceblog.ru/
http://scienceblog.ru/2009/04/22/5-nauchnykh-fokusov-s-vodojj/
http://dxdt.ru/
http://amp3direct.org/
http://amp3direct.org/category/raznoe/
http://cultureblog.ru/
http://cultureblog.ru/2008/12/
http://www.bloudoff.com/
http://www.bloudoff.com/labels/monography.html
http://liverss.ru/cat10/page2/feed28216/
http://liverss.ru/cat10/page2/feed28216/arch1/
http://blog.toodoo.ru/?p=1456
http://www.skuffelse.ru/
http://www.skuffelse.ru/2009/05/
http://prcy.myws.ru/sites/site/973
http://technorati.com/blogs/scienceblog.ru
http://www.internet.ru/node/9824
http://voliadis.ru/taxonomy/term/6
http://voliadis.ru/
http://scienceblog.mofuse.mobi/?page=show&type=item&f=33623&s=21272&id=3&sm=1&token=5cad744d70ed2c246d15e2d1e4876dcf
http://scienceblog.mofuse.mobi/?rk=eosnap
http://lemeshko.blogspot.com/2008/03/blog-post_22.html
http://www.niopasd.ru/
http://www.niopasd.ru/content/view/117/9/
http://www.infuture.ru/article/1195
http://window.edu.ru/window/catalog?p_mode=1&p_rid=50117&p_rubr=2.2
http://feeds2.feedburner.com/scienceblog-pod
http://pda.liverss.ru/cat10/page3/feed28216/

А запускаю этот скрипт с локалки

  Ответить  
 
 автор: cheops   (15.09.2009 в 20:06)   письмо автору
 
   для: dump   (15.09.2009 в 19:31)
 

Собственно value было приведено для примера - у вас этого члена нет - нужно использовать поле, которое идет в объекте. Перепишите лучше функцию get_yandex(), вернее одну строку
  return intval($ret[0]);

У вас на выходе будет обычный массив, который пропускайте через asort() или arsort(). У меня именно так получилось отсортировать ваши данные.

  Ответить  
 
 автор: dump   (15.09.2009 в 20:09)   письмо автору
 
   для: dump   (15.09.2009 в 19:31)
 

А вот сейчас эта проблема разрешилась сама... Я не знаю что это было, возможно какой-то глюк... Я применил стандартное arsort($output,SORT_NUMERIC) и массив отсортировался... Спасибо вам, конечно за то, что отвечали, я узнал от вас много нового.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования