2010-02-04 4 views
1

Я пишу IRCd. Для этой темы не имеет большого значения, если вы много знаете о IRC. Это простая проблема с кодом.Хороший способ разбить ответ на куски в рубине

Краткий обзор проблемы:

  • никакое сообщения может быть длиннее 512 символов
  • Если сообщение больше, она должна быть разбита на куски
  • В ИМЕНАХ ответа отправляет все прозвища пользователей на канале, и быстро вырастает более 512 символов.

Я в настоящее время придумал этот чудесный фрагмент кода, он отлично работает. Однако его просто не «рубиноподобный». Этот фрагмент кода больше того, что вы ожидаете в некотором фрагменте кода C.

# 11 is the number of all fixed characters combined in the reply 
pre_length = 11 + servername.length + mynick.length + channel.name.length 
list = [""] 
i = 0 
channel.nicks.each do |nick, client| 
    list[i+=1] = "" if list[i].length + nick.length + pre_length > 500 
    list[i] << "#{channel.mode_char(client)}#{client.nick} " 
end 
list.each { |l| send_numeric(RPL_NAMREPLY, channel.name, l.strip) } 
send_numeric(RPL_ENDOFNAMES, channel.name) 

Так что мой вопрос: любые идеи для этого лучше?

PS. код был слегка изменен, чтобы упростить понимание вне контекста

ответ

1

Я не могу придумать способ, чтобы упростить логику, но метод Enumerable#inject захватывает образец «построения результата при обходе списка»:

stuff = %w(my list of words) 
list = stuff.inject([""]) do |result,obj| 
    tsst = result[-1] + " " + obj 
    if tsst.length > 500 then result << obj else result[-1] = tsst end 
    result 
end 

(Здесь я просто работаю на массив строк.)

+0

Немного изменил поток сам, но именно то, что я искал. – user163365

0

Чтобы разбить строку на 512 строк символов, вы можете использовать некоторую магию Enumerator. Это требует рубин 1.8.7 или выше:

long_string.each_char.each_slice(512).map{ |chunk| chunk.join } 
+1

Я думаю, что одна из требований не колоть кого-то имя пополам. –

Смежные вопросы