- 1
- 2
- 3
- 4
- 5
$f=file('[путь к файлу]');
shuffle($f);
$f[0] - первая случайная строка
$f[1] - вторая случайная строка
$f[2] - третья случайная строка
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+158
$f=file('[путь к файлу]');
shuffle($f);
$f[0] - первая случайная строка
$f[1] - вторая случайная строка
$f[2] - третья случайная строка
вот PHP еще. если например несколько строк надо. ну и оптимальнее чем предложено выше.
http://megaobzor.com/forum-top-77608.html
Наверху было классическое
$quote=file('words.txt');
echo $quote[rand(0,count($quote)-1)];
а файл - бинарная последовательность. за исключением сервисных функций вроде file_get_contents и file, вся работа низкоуровнева подобно Си - fopen,fgetc,fclose.
В пхп даже нет такой привязки как в перле - хеши и dbm файлы
во втором пробег файла длителен
я могу поставить указатель в рандомное место и прочитать следующую за ним строчку.
ftell() скажет мне длину файла.
изречения вряд ли будут длиннее 100 символов.
соответственно, если ftell()>100, то ftell()-100 даст мне положение указателя 99% не на последней строке.
дальше я беру и читаю строку fgets'ом, предварительно прогнав его вхолостую, чтоб он перешел на новую строку.
как итог - я не бегал по файлу, а к чему ваши слова я вообще не понимаю.
Но ведь можно сначала файл преобразовать, чтобы строки были одинаковой длины, тогда ваш способ будет работать.
и то, можно хранить просто несклеенную копию, а пахать будет склеенная.
По-моему, этот код требует себе отдельную запись на этом сайте.
sed -n $((1 + $RANDOM % `wc -l file.txt`))p file.txt
а еще лучше shuf -n 1 file.txt
память у пхп больное место
это можно как-нибудь скормить консоли через похапе и получить ответ, затратив при этом меньше времени и средств, чем сам похапе?
echo system('shuf -n 1 ' . $filename); // выводит одну рандомную строку
если вдруг пакета не будет, можно попробовать вариант с sed
оба шустрые
но, как подсказывали парни, если скрипт соединяется с базой данных, то лучше залить данные в базу в виде "уникальный ключ - строка" и тянуть оттуда при помощи двух быстрых запросов, т.е. не использовать RAND() в запросе - он медленный, первым вынимать следующий ключ автоинкремента, рандомайзить на основе и выдергивать строку по рандомному ключу
и, да, насколько оно кроссплатформенно?
echo system('shuf -n 1 file.txt'); под виндой под денвером мне ничего не вывело.
В любом случае придется считывать весь файл. Если, конечно, заранее не известно количество строк. А если известно, то процесс можно несколько ускорить. И память можно сэкономить.
Вгляделся в код Люра, там как раз вроде что-то такое попытались сделать.
Что можно сделать?
Мое предложение вообще делать вот так
Насколько я знаю, здесь php нигде полностью файл не загрузит в память и размер файла не будет вообще играть роли.
Но я могу ошибаться.
И тут получается, чем длиннее строка, тем больше у нее шансов быть выбранной. Точнее не у нее, а у следующей за ней.
Если известно количество строк, то можно тупо fgets-ом пролистывать до строки со случайным номером в диапазоне от нуля до общего количества строк.
но давайте для наших рандомных фраз примем послабление - пусть они примерно одинаковой длины (+- 10 символов).
тогда мой код гк не будет, а как раз-таки самым оптимальным.
то есть для словаря, например, логинов или паролей мой код будет самым хорошим, чем листание fgets'ом, не так ли?
а если не вырастет, то
$quote=file('words.txt');
echo $quote[rand(0,count($quote)-1)];
самый оптимальный
разве это не самый топорный метод?
для дисциплины и упорядочения.
"зачем мне полочки и каталог для 10 книжек, я их лучше в углу покидаю"
проверочный код: 6666
Если файл имеет опредленное кол-во строк, то тогда, я думаю, хорошо будет просто рандомно прокручивать fgets до какой-либо строки.
Тогда можно сразу указывать какую строку вытаскивать.
Как правило, так оно и есть. Файл, содержащий некий набор "крылатых" фраз, подвергается изменениям крайне редко.
Так что есть смысл жёстко указать откуда именно следует расти ногам.
осталось приделать педали...
Или лучше на кассетах...
Тогда, действительно, "рандомно прокручивая магнитофоном"...
В моей практике был случай, когда рисовалась карта Москвы. Десяток миллионов точек в полигонах. Реляционная база данных довольно неплохо делала выборку для текущей области видимости, но расходы на IPC всё съедали. После перевода массива точек в файл появилась возможность значительно оптимизировать, поскольку не требовалось оптимальности. Прекеширование по районам, по соседним участкам, быстрый поиск - всё, что вообще нужно для комфортной работы.
Велосипед? Да, соглашусь. Но без него было бы нетривиально добиться вменяемой производительности.
Допустим там 100 строк и мне нужна 53-я.
Я кручу fgets 52 раза, а с 53 считываю.
Других способов считать строку, не зная позицию первого символа, невозможно.
Как это?
И с изречениями, разумеется, второй способ не прокатит, если, конечно, их пробелами не дозабить.
--
В первой строчке хранить указатели на начала строк изречений.
--
Вообще-то, хотите быстрее - храните список в памяти, процесс под это дело запустите, модуль расширения под php,..
(главное назвать это навроде "mysql")
:)
Второй вариант - выделение места под строку блоками определённого размера.
> Мое предложение вообще делать вот так...
imho:
Такой пример имеет право на существование в случае небольших нагрузок и объёма данных.
Либо как предложил sectus - делать строки одинаковой длины, либо индексировать содержимое (по указателям начала строк) и fseek'ать уже по индексу.
Либо изобретать новый велосипед - файловую систему...
БД (те которые под php), на большие (огромные) объёмы данных тоже не ахти как расчитаны, у них индекс, всё же, свопится на диск, и в конечном счёте - опять же приходится упираться в возможности ФС.
На мой взгляд - "кесарю - кесарево", возможности ресурсов должны оправдывать поставленные задачи.
А то потом придет насяльника и скажет: что ты весь день хуйней страдал, тут работы на пять минут? И обьясняй ему, что ты выискивал оптимальный алгоритм считывания случайной фразы
> под давлением сверху
Гастроэнтерология же ж.
и заполняется быстро, и включается одним include = ))))