2010-08-18 1 views
0

У меня есть массив целых чиселКак быстро печатать массив целых чисел в консоли?

a = [1,2,3,4] 

Когда я

a.join 

рубин внутренне вызывает метод to_s 4 раза, что является слишком медленным для моих потребностей.

Каков самый быстрый способ вывода большого массива целых чисел на консоль?

Я имею в виду:

a = [1,2,3,4........,1,2,3,9], should be: 

1234 ........ 1239

+0

Просто любопытно: зачем вам печатать так много на консоли? –

ответ

2

Как указано выше, если Fixnum.to_s комментарии не выполняет быстро достаточно для вас, тогда вам действительно нужно рассмотреть, является ли Ruby правильным инструментом для этой конкретной задачи.

Однако есть несколько вещей, которые вы могли бы сделать, которые могут или не могут быть применимы для вашей ситуации.

Если здание массива происходит за пределами критической области времени, тогда постройте массив или копию массива со строками вместо целых чисел. С моим небольшим тестом из 10000 целых чисел это примерно в 5 раз быстрее.

Если вы контролируете как чтение, так и процесс записи, используйте Array.pack для записи вывода и String.unpack, чтобы прочитать результат. Это может быть не быстрее, поскольку пакет, кажется, вызывает Fixnum.to_int, даже если элементы уже являются целыми.

Я ожидаю, что эти цифры будут отличаться для каждой версии Ruby, поэтому стоит проверить вашу конкретную целевую версию.

+0

Действительно, я сохранил более 2 секунд с массивом из более чем 1 млн. Элементов (Ruby 1.9.1) ставит [1,2,3 ..... n] .map {| c | с + 48} .pack ("с *") – astropanic

0

Медлительность в вас программа не приходит от to_s называют в 4 раза, но с печатью на консоль. Выход консоли медленный, и вы не можете ничего с этим поделать.

+0

Не совсем, конечно, выход на консоль медленный, но существует множество трюков, чтобы улучшить его, посмотрите на пример: http://stackoverflow.com/questions/3334294/ruby-fast-reading-from-std – astropanic

+0

Я бы согласился с FRotthowe на этом. Ограничением является сама консольная печать, а не то, как информация попадает на консоль. По внешнему виду обоих сообщений вы пытаетесь отправить данные из одного сценария другому через перенаправление ввода/вывода? –

+0

@ Ank-Kiet Ngo, да, я манипулирую массивом целых чисел, и мне нужно вернуть его в stdout, массив действительно большой, поэтому операции to_s занимают большую часть времени (ruby-prof) – astropanic

0

Для однозначных цифр вы можете сделать это

[1,2,3,4,5].map{|x|(x+48).chr}.join 

Если вам нужно ускорить большее количество вы можете попробовать memoizing результат to_s

+0

Я очень сомневаюсь, что это на самом деле быстрее. И, как оказалось, быстрый тест показывает, что карта + chr + join занимает около 1,75 раз до тех пор, пока соединение простое. – sepp2k

3

Если вы хотите напечатать целое число в stdout, вам нужно сначала преобразовать его в строку, так как это все stdout понимает. Если вы хотите напечатать два целых числа в stdout, вам нужно сначала преобразовать их в строку. Если вы хотите напечатать три целых числа в stdout, вам нужно сначала преобразовать все три из них в строку. Если вы хотите напечатать один миллиард целых чисел в stdout, вам нужно сначала преобразовать весь один миллиард из них в строку.

Нет ничего, что вы, мы, или Ruby, или действительно любой язык программирования может это сделать.

Вы можете попробовать чередование преобразования с помощью ввода-вывода, выполняя ленивую реализацию потока. Вы можете попытаться выполнить преобразование и ввод-вывод параллельно, выполняя ленивую реализацию потока и разделяя преобразование и ввод-вывод на два отдельных потока.(Не забудьте использовать реализацию Ruby, который может на самом деле выполнение параллельных потоков, а не все из них могут:. МРТ, YARV и Rubinius не могут, например)

Вы можете распараллелить преобразование, путем преобразования отдельных кусков в массиве в отдельных потоках параллельно. Вы даже можете купить миллиардную ядерную машину и одновременно конвертировать все миллиарды целых чисел параллельно.

Но даже тогда факт остается фактом: каждое целое число необходимо преобразовать. Выполняете ли вы это один за другим первым, а затем печатаете их или делаете это один за другим, чередуясь с вводом-выводом, или делаете это один за другим параллельно с вводом-выводом или даже конвертируете все из них в одно и то же время на миллиард основных процессоров: количество необходимых преобразований не волшебным образом уменьшается. Большое количество целых чисел означает большое количество преобразований. Даже если вы делаете все миллиарды конверсий в миллиард основных процессоров параллельно, то все еще миллиард конверсий, т. Е. Миллиард звонков на to_s.

0

Если вам действительно не нужно видеть номера на консоли (и, похоже, это не так), то записывайте их в файл в двоичном формате - должно быть намного быстрее.

И вы можете передавать двоичные файлы в другие программы, если это то, что вам нужно сделать, а не только текст.