Как вывести топ ячеек из файла
1.
Дмитрий (11.01.2010 / 07:19)
Есть файл, назовем его "myfile.dat"
Файл содержит множество строк, каждая из которых состоит из 10 ячеек. Пятая ячейка содержит баллы (вроде рейтинга).
Как в файле отсортировать строки по пятой ячейке (чем больше в ней число, тем выше строка, и исключить из рейтинга ячейки с отрицательным значением и "0"). Я так понимаю, что файл нужно перезаписывать... Чет не получается...
2.
ramzes (11.01.2010 / 15:52)
Если заранее известно что нужна сложная сортировка то используй мускул, или хотя бы структуру файла составляй так что бы было удобно это делать.
Тебе надо создать массив с ключами из этой 5 ячейки и отсортировать по ключу его.
3.
Артур (11.01.2010 / 23:06)
Добрый вечер.
Давненько здесь небыл
Собственно по теме скажу, что такая система работы с
удаленными данными, если я не ошибаюсь, когда то получила название -
база данных с удаленными файлами. Немного о ней, а после вернусь к теме.
ФБД(файловая база данных без СУБД)
Принцип работы у таких баз данных схож с обработкой файлов на таких языках программирования как С/С+ и 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)
Алиган, согласен, предпочел бы мускул, но раз автор просит, пишу ему более сложный метод
10.
Олег (11.01.2010 / 23:28)
я про него кстати ничего не слышал. Ты случаем не dbf - формат имеешь ввиду?
11.
Артур (11.01.2010 / 23:29)
Можно попытаться уменьшить ресурсоемкость разделением файла данных на подфайлы если знаем в какой части искать данные, либо сильным модульным разделением данных на подфайлы данных объединенные одним головным файлом, так же простой поиск данных или их фильтрация в подобных файлах вполне уместен, а упорядочивание целого файла это редкая процедура, в современных СУБД уже не используемая.
12.
Артур (11.01.2010 / 23:30)
Алиган, я предлагаю написание отдельного класса для работы с файлами данных, какое расширение будет иметь этот файл совершенно не важно
13.
Олег (11.01.2010 / 23:46)
Да смысла нет делать это на уровне интерпретируемого языка программирования. Я это к тому что хорошего эффекта не получить. Если касается для ведения какой-то статистики или инструментария для ведения лог-файлов, то да, будет удобно.
14.
Артур (11.01.2010 / 23:53)
Смысло конечно мало, но я не знаю для чего это понадобилось автору, а ответ на такой вопрос получу минимум завтра
потому без разбора написал что думал по теме. Нужно будет как нибудь набрать такой класс. В уме курятся файлы данных на .хмл, думаю выигрышь в скорости получим.
15.
ramzes (12.01.2010 / 03:18)
Гм.. Мощно задвинули.. Внушает, правда есть одно но, вместом написания класса лучше потратить столько же времени на изменение скрипта, (мускул или выносной файл с нужными ключами,(фактически та же система), на худой конец кеширование).
Автору конечно виднее, но сам ход изначально не рационален. Файлы хороши для хранения и выборки простой информации без сложных условий и прочего,
иначе вся система будет проходить через это узкое горлышко.
Наступит день когда файл разрастется на столько что будет ощутимо тормозить, и тогда придется переделывать уже гораздо больше кода завязанного на этом файле. (пример: мотор18. Все хотят на реглобалс офф перевести но работы то сколько..).
Кто сказал что оптимизация должна начинаться после написания скрипта тот видимо не писал на ходу или на заказ, сделал - отдал - забыл
такое вот мое скромное мнение..
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ой ячейкой исключены.
Собственно в задаче вроде это и было
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);
да, поторопился там маленько
этот работать должен как надо
пришлось попотеть что бы уникальные ключи генерить
и то фиг его знает, не проверял как работает.
Файлы - ацтой, адназначна.
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);
и посмотри результат сортировки. Я вчера проверил, на пяти записях но все же
не лучший ход но работало.
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 минут проб. Попробуй. Потом еще спасибо скажешь что уговорили
я тоже раньше думал мускул сложно, файлы сложнее и геморойнее из-за отсутствия гибкости.
Щас фиг заставишь что на файлах писать кроме счетчиков
<?php
$stat = $mysql->query("SELECT * FROM topuser ORDER BY totalpost DESC;");
while( $print = $stat->fetch_assoc()){
print_r($print);
}
сравни? Вот на мускуле как этот твой скрипт будет выглядеть
проще просто не куда.
#25 implode через \r\n обьединяешь? По этому и пустая строка.
31.
Олег (13.01.2010 / 19:35)
На мускуле этот скрипт может такого маху дать, что на клиентской стороне браузер в течение быстрого времени задействует всю ОП клиентской машины. А все потому что нет лимита в запросе.
32.
Дмитрий (14.01.2010 / 07:34)
Все-таки дописал. На файлах. На мускул позже переделаю. Аптеки расставил
Вот еще вопрос. Как мне в файл кеша записать ТОЛЬКО 20 строк (типа, 20 лучших)? Что добавить в код?
33.
Артур (14.01.2010 / 08:24)
Файл кэша? Это что за файл такой?
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, ну, как ты говоришь - эт посложнее код будет моего-то
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)
Мда, интернет не позволяет. Вечером передам
Ну как там?
45.
ramzes (20.01.2010 / 01:45)
Перед записью
<?php
for($i=0; $i<20; $i++){
$savemass.=$result[$i]."\r\n";
}
unset($result);
записывать в файл переменную $savemass, ни чего с ней делать не надо она уже отформатирована как надо.
Ключ со ста я уже не помню почему начинал
по моему что бы ключ не сделал число длиннее предыдущего на единицу..
46.
Артур (20.01.2010 / 03:03)
Блин, забыл
щас дам
47.
Артур (20.01.2010 / 03:30)
http://upwap.ru/717020
Там три варианта, лучше чем ~ 6,8Е-4 не вышло, если у кого получится до 6 или 5 довести, прошу показать
В индекс2 готовая функция с описанием, скорость работы ~ 7Е-4 построчным чтением из файла
48.
Артур (20.01.2010 / 05:40)
Наверно нужно было еще проверить работу с большими файлами, так как в этом случае построчное чтение в цикле может занять куда больше времени чем чтение сразу в массив (которое кстати показало лучшее время), и если это так, то написать функцию для другого метода.
49.
Дмитрий (20.01.2010 / 06:36)
В принципе, речь шла об этом скрипте:
http://inter-sky.net/x-traz/index.php и о его ТОП-20
URL:
https://visavi.net/topics/4811