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

#arrays #ruby #default-value

#массивы #ruby #значение по умолчанию

Вопрос:

Это тривиальный вопрос, не уверен, действительно ли я должен спрашивать здесь, но хотел бы узнать, есть ли у кого-нибудь более элегантный способ написать это на ruby.

У меня есть строка версии формата x.y.z или x.y или x . Я хотел бы простой элегантный способ преобразовать это в массив, в который вставляется значение по умолчанию 0, если сегмент отсутствует. У меня есть несколько разных способов сделать это, но я надеялся на что-то более чистое. Atm мое текущее решение таково

 version_string.split('.').each_with_index.with_object(['0','0','0']) { |(segment, i), version_array| version_array[i] = segment }
 

Кажется, работает нормально, и я всегда могу перейти к простому вызову метода, чтобы сделать код похожим на очистку, но что-то в использовании each_with_index and `with_object меня немного беспокоит. Просто любопытно посмотреть, есть ли у остальной части сообщества Ruby что добавить

Комментарии:

1. Я действительно не чувствую, что это особенно элегантно, но вы можете использовать регулярное выражение для синтаксического анализа «1», «1.2», «1.2.3» в списки из 3 элементов, где недостающие числа будут равны нулю. /(d)(?:.(d))?(?:.(d))?/.match(string)[1..-1] например , для string="1.2" того , чтобы он вернулся [1,2,nil] . Тогда вы могли бы поработать map { |num| num || 0 } над результатом, прежде чем присоединиться. Хотелось бы, чтобы был способ сделать подобное ljust для массивов, но я ничего не вижу.

2. Почему бы вам не использовать такой драгоценный камень, как versionomy ?

3. /(d ).?(d )?.?(d )?/.match(str).captures.map {|s| s.to_i.to_s} будет работать. @maxpleaner вы могли бы смоделировать концепцию в 2 этапа str.scan(/d /).concat(['0','0','0']).first(3) или ['0','0','0'].unshift(*str.scan(/d /)).first(3)

4. Самая сложная вещь, которую я могу придумать, str.split(?.). ([?0]*3)[..2] но это предполагает, что «0» (ы) не будут изменены позже

Ответ №1:

Как насчет (минимум Ruby 2.6)

 version_string.split('.').then { |x, y = '0', z = '0'| [x,y,z] }