- 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)];
Lure Of Chaos 02.02.2011 00:34 # −1
7ion 02.02.2011 00:35 # 0
Lure Of Chaos 02.02.2011 00:37 # −2
7ion 02.02.2011 00:39 # −2
Lure Of Chaos 02.02.2011 00:43 # −3
а файл - бинарная последовательность. за исключением сервисных функций вроде file_get_contents и file, вся работа низкоуровнева подобно Си - fopen,fgetc,fclose.
В пхп даже нет такой привязки как в перле - хеши и dbm файлы
7ion 02.02.2011 00:47 # 0
Lure Of Chaos 02.02.2011 00:57 # −3
во втором пробег файла длителен
7ion 02.02.2011 00:59 # −2
я могу поставить указатель в рандомное место и прочитать следующую за ним строчку.
Lure Of Chaos 02.02.2011 01:00 # −3
7ion 02.02.2011 01:07 # −2
ftell() скажет мне длину файла.
изречения вряд ли будут длиннее 100 символов.
соответственно, если ftell()>100, то ftell()-100 даст мне положение указателя 99% не на последней строке.
дальше я беру и читаю строку fgets'ом, предварительно прогнав его вхолостую, чтоб он перешел на новую строку.
как итог - я не бегал по файлу, а к чему ваши слова я вообще не понимаю.
sectus 02.02.2011 05:01 # +2
Но ведь можно сначала файл преобразовать, чтобы строки были одинаковой длины, тогда ваш способ будет работать.
Uchkuma 02.02.2011 00:43 # 0
Lure Of Chaos 02.02.2011 00:47 # −3
7ion 02.02.2011 00:48 # −1
Lure Of Chaos 02.02.2011 00:55 # −2
7ion 02.02.2011 00:58 # −3
Lure Of Chaos 02.02.2011 01:01 # −3
7ion 02.02.2011 01:10 # −4
и то, можно хранить просто несклеенную копию, а пахать будет склеенная.
wmmorgun 02.02.2011 10:19 # +3
Lure Of Chaos 02.02.2011 00:39 # −3
7ion 02.02.2011 00:39 # 0
Lure Of Chaos 02.02.2011 00:48 # −3
7ion 02.02.2011 00:51 # 0
По-моему, этот код требует себе отдельную запись на этом сайте.
Lure Of Chaos 02.02.2011 00:59 # −4
7ion 02.02.2011 00:59 # +1
p5ych0 02.02.2011 00:53 # 0
sed -n $((1 + $RANDOM % `wc -l file.txt`))p file.txt
а еще лучше shuf -n 1 file.txt
память у пхп больное место
7ion 02.02.2011 00:56 # 0
это можно как-нибудь скормить консоли через похапе и получить ответ, затратив при этом меньше времени и средств, чем сам похапе?
p5ych0 02.02.2011 01:08 # 0
echo system('shuf -n 1 ' . $filename); // выводит одну рандомную строку
если вдруг пакета не будет, можно попробовать вариант с sed
оба шустрые
но, как подсказывали парни, если скрипт соединяется с базой данных, то лучше залить данные в базу в виде "уникальный ключ - строка" и тянуть оттуда при помощи двух быстрых запросов, т.е. не использовать RAND() в запросе - он медленный, первым вынимать следующий ключ автоинкремента, рандомайзить на основе и выдергивать строку по рандомному ключу
7ion 02.02.2011 01:16 # −1
и, да, насколько оно кроссплатформенно?
echo system('shuf -n 1 file.txt'); под виндой под денвером мне ничего не вывело.
p5ych0 02.02.2011 01:19 # +2
bugmenot 02.02.2011 06:07 # +6
Uchkuma 02.02.2011 01:04 # 0
В любом случае придется считывать весь файл. Если, конечно, заранее не известно количество строк. А если известно, то процесс можно несколько ускорить. И память можно сэкономить.
Вгляделся в код Люра, там как раз вроде что-то такое попытались сделать.
7ion 02.02.2011 01:09 # 0
Что можно сделать?
Мое предложение вообще делать вот так
Насколько я знаю, здесь php нигде полностью файл не загрузит в память и размер файла не будет вообще играть роли.
Но я могу ошибаться.
Uchkuma 02.02.2011 01:17 # 0
И тут получается, чем длиннее строка, тем больше у нее шансов быть выбранной. Точнее не у нее, а у следующей за ней.
Если известно количество строк, то можно тупо fgets-ом пролистывать до строки со случайным номером в диапазоне от нуля до общего количества строк.
7ion 02.02.2011 01:20 # 0
но давайте для наших рандомных фраз примем послабление - пусть они примерно одинаковой длины (+- 10 символов).
тогда мой код гк не будет, а как раз-таки самым оптимальным.
то есть для словаря, например, логинов или паролей мой код будет самым хорошим, чем листание fgets'ом, не так ли?
p5ych0 02.02.2011 01:30 # 0
7ion 02.02.2011 01:36 # 0
p5ych0 02.02.2011 01:41 # 0
а если не вырастет, то
$quote=file('words.txt');
echo $quote[rand(0,count($quote)-1)];
самый оптимальный
7ion 02.02.2011 01:49 # 0
разве это не самый топорный метод?
Lure Of Chaos 02.02.2011 12:39 # −2
Lure Of Chaos 02.02.2011 12:41 # −2
для дисциплины и упорядочения.
"зачем мне полочки и каталог для 10 книжек, я их лучше в углу покидаю"
проверочный код: 6666
istem 02.02.2011 02:12 # +1
eth0 03.02.2011 21:17 # 0
7ion 03.02.2011 21:21 # 0
Если файл имеет опредленное кол-во строк, то тогда, я думаю, хорошо будет просто рандомно прокручивать fgets до какой-либо строки.
istem 04.02.2011 02:04 # 0
Тогда можно сразу указывать какую строку вытаскивать.
Как правило, так оно и есть. Файл, содержащий некий набор "крылатых" фраз, подвергается изменениям крайне редко.
Так что есть смысл жёстко указать откуда именно следует расти ногам.
bugmenot 04.02.2011 02:40 # +1
осталось приделать педали...
istem 04.02.2011 02:47 # 0
Или лучше на кассетах...
Тогда, действительно, "рандомно прокручивая магнитофоном"...
eth0 04.02.2011 19:34 # 0
В моей практике был случай, когда рисовалась карта Москвы. Десяток миллионов точек в полигонах. Реляционная база данных довольно неплохо делала выборку для текущей области видимости, но расходы на IPC всё съедали. После перевода массива точек в файл появилась возможность значительно оптимизировать, поскольку не требовалось оптимальности. Прекеширование по районам, по соседним участкам, быстрый поиск - всё, что вообще нужно для комфортной работы.
Велосипед? Да, соглашусь. Но без него было бы нетривиально добиться вменяемой производительности.
7ion 04.02.2011 12:11 # 0
Допустим там 100 строк и мне нужна 53-я.
Я кручу fgets 52 раза, а с 53 считываю.
Других способов считать строку, не зная позицию первого символа, невозможно.
istem 04.02.2011 12:17 # 0
7ion 04.02.2011 12:36 # 0
Как это?
И с изречениями, разумеется, второй способ не прокатит, если, конечно, их пробелами не дозабить.
istem 04.02.2011 13:00 # 0
--
В первой строчке хранить указатели на начала строк изречений.
--
Вообще-то, хотите быстрее - храните список в памяти, процесс под это дело запустите, модуль расширения под php,..
(главное назвать это навроде "mysql")
:)
eth0 04.02.2011 19:37 # 0
Второй вариант - выделение места под строку блоками определённого размера.
istem 02.02.2011 14:19 # 0
> Мое предложение вообще делать вот так...
imho:
Такой пример имеет право на существование в случае небольших нагрузок и объёма данных.
Либо как предложил sectus - делать строки одинаковой длины, либо индексировать содержимое (по указателям начала строк) и fseek'ать уже по индексу.
Либо изобретать новый велосипед - файловую систему...
БД (те которые под php), на большие (огромные) объёмы данных тоже не ахти как расчитаны, у них индекс, всё же, свопится на диск, и в конечном счёте - опять же приходится упираться в возможности ФС.
На мой взгляд - "кесарю - кесарево", возможности ресурсов должны оправдывать поставленные задачи.
Lure Of Chaos 02.02.2011 14:43 # 0
А то потом придет насяльника и скажет: что ты весь день хуйней страдал, тут работы на пять минут? И обьясняй ему, что ты выискивал оптимальный алгоритм считывания случайной фразы
istem 02.02.2011 15:14 # 0
Lure Of Chaos 02.02.2011 15:17 # 0
gegMOPO4 02.02.2011 15:19 # 0
istem 02.02.2011 15:38 # 0
> под давлением сверху
Гастроэнтерология же ж.
Lure Of Chaos 02.02.2011 12:46 # 0
и заполняется быстро, и включается одним include = ))))
Lure Of Chaos 02.02.2011 14:40 # +4