Как вывести топ ячеек из файла

1. Дмитрий (11.01.2010 / 07:19)
Есть файл, назовем его "myfile.dat"
Файл содержит множество строк, каждая из которых состоит из 10 ячеек. Пятая ячейка содержит баллы (вроде рейтинга).
Как в файле отсортировать строки по пятой ячейке (чем больше в ней число, тем выше строка, и исключить из рейтинга ячейки с отрицательным значением и "0"). Я так понимаю, что файл нужно перезаписывать... Чет не получается... lamer

2. ramzes (11.01.2010 / 15:52)
Если заранее известно что нужна сложная сортировка то используй мускул, или хотя бы структуру файла составляй так что бы было удобно это делать.
Тебе надо создать массив с ключами из этой 5 ячейки и отсортировать по ключу его.

3. Артур (11.01.2010 / 23:06)
Добрый вечер.
Давненько здесь небыл smile
Собственно по теме скажу, что такая система работы с удаленными данными, если я не ошибаюсь, когда то получила название - база данных с удаленными файлами. Немного о ней, а после вернусь к теме.
ФБД(файловая база данных без СУБД)
Принцип работы у таких баз данных схож с обработкой файлов на таких языках программирования как С/С+ и Pascal и состоит из нескольких шагов:
1. Чтение файла в ОП (оперативная память)
2. Обработка данных в ОП
3. Перезапись данных в файл

4. Артур (11.01.2010 / 23:11)
Чтение файла в ОП
Есть получение строк файла в массив строк ОП. До появления РБД (реляционных баз данных) чтение проходило в одномерный массив строк. После появления систем разграничения сущностей и атрибутов чтение стало проходить в матрицу строк следующего вида:
Файл->Строка->Данные между разделителями>>array[i][j]
где i - номер сущности
j - номер атрибута
Таким образом любой файл с подходящей структурой может быть представлен в памяти в виде реляционной базы данных

5. Артур (11.01.2010 / 23:13)
Обработка данных в ОП
Представляет собой обработку с помощью стандартных методов работы с многомерными массивами данных и строками.

6. Артур (11.01.2010 / 23:19)
Перезапись данных в файл
Наиболее ответственный момент. До этого момента данные, что называется, кэшируются, то есть обрабатываются в ОП и любые действия могут быть исправлены без обращения к файлу данных. Такой подход поддерживает транзагниттивность обращения к файлу данных. После отправки данных на запись, файл данных очищается и заполняется измененным содержанием по особой схеме представленной ниже:
array[i][j++]>>Файл>>Разделитель атрибута
array[i++][j]>>Файл>>Разделитель сущности

7. Олег (11.01.2010 / 23:23)
Только эти стандартные методы очень ресурсоемки для работы с многопользовательскими запросами.

8. Артур (11.01.2010 / 23:25)
Теперь по вопросу темы
Во первых, автор, структурируй все свой файлы данных чтобы они имели разделители атрибутов, на пример по следующиму принципу
атрибут 1|атрибут 2|атрибут 3
атрибут 1|атрибут 2|атрибут 3
. . .
атрибут 1|атрибут 2|атрибут 3
здесь символ | будет разделять атрибуты, а перенос строки разделять сущности.
После чего учитывай весь файл в массив, в PHP это не составит проблем и разделяй каждую строку по символу разделителя атрибута, то есть |. Получим матрицу данных. Затем циклически или с помощью функций проходим по всем сущностям и меняем их местами если значение определенного атрибута меньше или больше следующего, а атрибуты с отрицательным значением удаляем полность. После чего записываем полученное в файл.

9. Артур (11.01.2010 / 23:26)
Алиган, согласен, предпочел бы мускул, но раз автор просит, пишу ему более сложный метод smile

10. Олег (11.01.2010 / 23:28)
я про него кстати ничего не слышал. Ты случаем не dbf - формат имеешь ввиду?

11. Артур (11.01.2010 / 23:29)
Можно попытаться уменьшить ресурсоемкость разделением файла данных на подфайлы если знаем в какой части искать данные, либо сильным модульным разделением данных на подфайлы данных объединенные одним головным файлом, так же простой поиск данных или их фильтрация в подобных файлах вполне уместен, а упорядочивание целого файла это редкая процедура, в современных СУБД уже не используемая.

12. Артур (11.01.2010 / 23:30)
Алиган, я предлагаю написание отдельного класса для работы с файлами данных, какое расширение будет иметь этот файл совершенно не важно smile

13. Олег (11.01.2010 / 23:46)
Да смысла нет делать это на уровне интерпретируемого языка программирования. Я это к тому что хорошего эффекта не получить. Если касается для ведения какой-то статистики или инструментария для ведения лог-файлов, то да, будет удобно.

14. Артур (11.01.2010 / 23:53)
Смысло конечно мало, но я не знаю для чего это понадобилось автору, а ответ на такой вопрос получу минимум завтра smile потому без разбора написал что думал по теме. Нужно будет как нибудь набрать такой класс. В уме курятся файлы данных на .хмл, думаю выигрышь в скорости получим.

15. ramzes (12.01.2010 / 03:18)
Гм.. Мощно задвинули.. Внушает, правда есть одно но, вместом написания класса лучше потратить столько же времени на изменение скрипта, (мускул или выносной файл с нужными ключами,(фактически та же система), на худой конец кеширование).
Автору конечно виднее, но сам ход изначально не рационален. Файлы хороши для хранения и выборки простой информации без сложных условий и прочего,
иначе вся система будет проходить через это узкое горлышко.
Наступит день когда файл разрастется на столько что будет ощутимо тормозить, и тогда придется переделывать уже гораздо больше кода завязанного на этом файле. (пример: мотор18. Все хотят на реглобалс офф перевести но работы то сколько..).
Кто сказал что оптимизация должна начинаться после написания скрипта тот видимо не писал на ходу или на заказ, сделал - отдал - забылsmile
такое вот мое скромное мнение..

16. Игорь (12.01.2010 / 03:26)
А что если (это просто догатки мож и не верные) если разбить с помощью explode, потом записать в массив и сортировать его и записать...Что вроде этого..ХЗ

17. Игорь (12.01.2010 / 03:32)
<?
  $u=file(BASEDIR."/file.txt");
  $udata=explode(":||:", $u[0]);
sort($udata[5]); //плин че то вертиться на уме..


18. ramzes (12.01.2010 / 03:47)
<?php
$file = file('file.txt'); // берем файл
$key = array();
$result = array();
foreach($file as $line=>$data){
$d = explode('|',$data);
if($d[5]!=""){
$key[] = $line; // формируем массив с ключами
}}
sort($key); // сортируем
foreach($key as $id){
$result[]=$file[$id]; // формируем массив результата 
}
unset($key);
unset($file);
print_r($result);
легче придумать не смог.

19. Игорь (12.01.2010 / 04:52)
Он выводит что то типо
<?
Array ( [0] => asdasd|asdasdas|asdsada|asdsad|asdasd|1|asdsad| [1] => asdasd|asdasdas|asdsada|asdsad|asdasd|2|asdsad| [2] => asdasd|asdasdas|asdsada|asdsad|asdasd|3|asdsad| [3] => asdasd|asdasdas|asdsada|asdsad|asdasd|4|asdsad| )


20. ramzes (12.01.2010 / 04:56)
Да, будет эффект как будто $result = file('file.txt');
но сразу отсортировано по 5ой ячейке и строчки с пустой 5ой ячейкой исключены.
Собственно в задаче вроде это и былоsmile

21. Игорь (12.01.2010 / 05:05)
ОН наверно хотел так:
text|text|text|text|text|4|text|
text|text|text|text|text|2|text|
text|text|text|text|text|1|text|
text|text|text|text|text|3|text|
И что бы после выполнения скрипта получалось так:
text|text|text|text|text|1|text|
text|text|text|text|text|2|text|
text|text|text|text|text|3|text|
text|text|text|text|text|4|text|

22. ramzes (12.01.2010 / 05:10)
Ну так и получилось))

23. Игорь (12.01.2010 / 05:20)
<?
Array ( [0] => text|text|text|text|text|4|text| [1] => text|text|text|text|text|2|text| [2] => text|text|text|text|text|1|text| [3] => text|text|text|text|text|3|text| ) //выполнение скрипта
Содержимое file.txt:
text|text|text|text|text|4|text|
text|text|text|text|text|2|text|
text|text|text|text|text|1|text|
text|text|text|text|text|3|text|
Не сортерует)

24. ramzes (12.01.2010 / 06:41)
<?
$file = file('file.txt');
$s = 100;
foreach($file as $line=>$data){
$d = explode('|',$data);
if($d[5]>0){
$key[$d[5].$s] = $line;
if($s<=998){
$s++;
}else{
$s = 100;
}}}
ksort($key);
foreach($key as $i=>$k){
$result[]=$file[$k]; }
print_r($result);
unset($file);
unset($key);
да, поторопился там маленькоsmile
этот работать должен как надоsmile пришлось попотеть что бы уникальные ключи генеритьsmile и то фиг его знает, не проверял как работает.
Файлы - ацтой, адназначна.

25. Дмитрий (13.01.2010 / 02:55)
24. ramzes, ХЗ почему, но все равно не сортирует и первую строчку выводит пустую
Я делал таким макаром:
$file = file($datarand); 
$s = 100; 
foreach($file as $line=>$data){ 
$d = explode('|',$data); 
if($d[3]>0){ 
$key[$d[3].$s] = $line; 
if($s<=998){ 
$s++; 
}else{ 
$s = 100; 
}}} 
ksort($key); 
foreach($key as $i=>$k){
$result[]=$file[$k]; } 
unset($file); 
unset($key);
$result=implode("",$result);
if($result!=""){
$fp = fopen($datatop,"a+");
flock ($fp,LOCK_EX);
ftruncate ($fp,0);
fputs($fp,"$result\r\n");
fflush ($fp);
flock ($fp,LOCK_UN);
fclose($fp);
chmod ($fp, 0666); 
chmod ($datatop, 0666); 
}
$datarand - файл, ОТКУДА берутся данные
$datatop - файл, КУДА пишется кеш

26. ramzes (13.01.2010 / 03:31)
Не может по определению пустых строк быть. Посмотри как формируется массив $кей, даже если бы каким то чудом попал бы пустой ключ то все равно к нему префикс $с прилип бы.
Это ты что то при записи не так сделал видимо, поставь print_r($key);
print_r($result);
и посмотри результат сортировки. Я вчера проверил, на пяти записях но все жеsmile не лучший ход но работало.

27. Дмитрий (13.01.2010 / 04:06)
Я догадываюсь, откуда пустая строка берется...
"а+" пишет строку и оставляет указатель на последней ПУСТОЙ строке.
Возможно, потому что этот файл копируется, сортируется и перезаписывается, создается ВТОРАЯ пустая нижняя строка, которая и выводится на экран.
В принципе, так и есть, вот как копирнуть файл, чтобы в запись шли только записаные строки...

28. Олег (13.01.2010 / 06:39)
LondoN_tm, неужели тебе сложно это на SQL сделать? Код станет всего в 2 строчки и гемороя меньше.
по существу когда данные будут за 1 мб file() будет грузить процессоре php, лучше на fopen поменять.

29. Дмитрий (13.01.2010 / 08:08)
28. Aligan, дело в том, что я не знаю SQL. A скрипт я уже накатал на файлах. Осталось к нему топ прикрутить, с которым я и мучаюсь.

30. ramzes (13.01.2010 / 09:17)
Да там знать то не чего, в частности для данного примера достаточно знать инсерт инто и селект. Это максимум 20 минут чтения и 20 минут проб. Попробуй. Потом еще спасибо скажешь что уговорилиsmile я тоже раньше думал мускул сложно, файлы сложнее и геморойнее из-за отсутствия гибкости.
Щас фиг заставишь что на файлах писать кроме счетчиковsmile
<?php
$stat = $mysql->query("SELECT * FROM topuser ORDER BY totalpost DESC;");
while( $print = $stat->fetch_assoc()){
print_r($print);
}
сравни? Вот на мускуле как этот твой скрипт будет выглядетьsmile проще просто не куда.
#25 implode через \r\n обьединяешь? По этому и пустая строка.

31. Олег (13.01.2010 / 19:35)
На мускуле этот скрипт может такого маху дать, что на клиентской стороне браузер в течение быстрого времени задействует всю ОП клиентской машины. А все потому что нет лимита в запросе.

32. Дмитрий (14.01.2010 / 07:34)
Все-таки дописал. На файлах. На мускул позже переделаю. Аптеки расставил smile
Вот еще вопрос. Как мне в файл кеша записать ТОЛЬКО 20 строк (типа, 20 лучших)? Что добавить в код?

33. Артур (14.01.2010 / 08:24)
Файл кэша? Это что за файл такой? smile

34. Дмитрий (14.01.2010 / 08:40)
33. Bashka, глянь мой пост №25. Я сделал так, как там написал.

35. Артур (14.01.2010 / 08:50)
Какой то сложноватый код у тебя получился. Зачем ключ со ста начинать, разве нельзя с нуля и дальше? Дальше не стал разбирать.

36. Артур (14.01.2010 / 08:51)
Чтобы добавить в файл двадцать лучшних, найди максимальное значение ключа и в цикле пройди 20 итераций вниз записывая каждый раз строку в файл

37. Артур (14.01.2010 / 08:53)
Упс, скопировался пост. Нехорошо

38. Дмитрий (14.01.2010 / 09:18)
36. Bashka, ну, как ты говоришь - эт посложнее код будет моего-то smile

39. Артур (14.01.2010 / 09:27)
Сейчас посмотрим

40. Артур (14.01.2010 / 11:26)
Закончил вроде. Сейчас попробую функцию скинуть

41. Артур (14.01.2010 / 11:36)
Мда, интернет не позволяет. Вечером передам

42. Артур (14.01.2010 / 11:37)
Мда, интернет не позволяет. Вечером передам

43. Олег (14.01.2010 / 14:07)
Только нужно помнить прежде чем брать из кеша, нужно проверять дату последнего изменения. См. filemtime()

44. Дмитрий (19.01.2010 / 18:07)
Bashka (14.01.10 / 10:26)
Закончил вроде. Сейчас попробую функцию скинуть
Bashka (14.01.10 / 10:36)
Мда, интернет не позволяет. Вечером передам
Ну как там? smile

45. ramzes (20.01.2010 / 01:45)
Перед записью
<?php
for($i=0; $i<20; $i++){
$savemass.=$result[$i]."\r\n";
}
unset($result);
записывать в файл переменную $savemass, ни чего с ней делать не надо она уже отформатирована как надо.
Ключ со ста я уже не помню почему начиналsmile по моему что бы ключ не сделал число длиннее предыдущего на единицу..

46. Артур (20.01.2010 / 03:03)
Блин, забыл smile щас дам

47. Артур (20.01.2010 / 03:30)
http://upwap.ru/717020
Там три варианта, лучше чем ~ 6,8Е-4 не вышло, если у кого получится до 6 или 5 довести, прошу показать smile В индекс2 готовая функция с описанием, скорость работы ~ 7Е-4 построчным чтением из файла

48. Артур (20.01.2010 / 05:40)
Наверно нужно было еще проверить работу с большими файлами, так как в этом случае построчное чтение в цикле может занять куда больше времени чем чтение сразу в массив (которое кстати показало лучшее время), и если это так, то написать функцию для другого метода.

49. Дмитрий (20.01.2010 / 06:36)
В принципе, речь шла об этом скрипте:
http://inter-sky.net/x-traz/index.php и о его ТОП-20 smile

URL: https://visavi.net/topics/4811