2015-09-16 3 views
1

У меня есть хэш, как это:массива в строку с конкретным форматом

@password_constraints = { 
    length: 'Must be at least 6 character long.', 
    contain: [ 
     'one number', 
     'one lowercase letter', 
     'one uppercase letter.' 
    ] 
} 

И я хочу написать метод, который возвращает строку удобочитаемой, построенную из этого хэша, как этот:

Длина должна быть не менее 6 символов. Должно содержать: одно число, одну строчную букву и заглавную букву.

В настоящее время, у меня есть очень подробный метод с each, что перебирает в @password_constraints[:contain] массива и имеет несколько условий, чтобы проверить, если я должен поставить ,, или and или ничего.

Но я хочу почти то же поведение, что и join(', '), но последний разделитель должен быть and.

Я ищу какое-то решение, как этот с особой join:

def password_constraints 
    @password_constraints[:length] << ' Must contain.' << @password_constraints[:contain].join(', ') 
end 

Есть ли способ, чтобы сделать это более компактный или Ruby, как?

ответ

4

Вы можете использовать оператор пейнтбольный разделить массив и просто проверить случай, если есть только одна строка:

def message(constraints) 
    *others, second_last, last = constraints[:contain] 
    second_last += " and #{last}" unless last.nil? 
    "#{constraints[:length]} Must contain: #{(others << second_last).join(', ')}" 
end 

@password_constraints = { 
    length: 'Must be at least 6 character long.', 
    contain: [ 
     'one number', 
     'one lowercase letter', 
     'one uppercase letter.' 
    ] 
} 

message(@password_constraints) 
# => "Must be at least 6 character long. Must contain: one number, one lowercase letter and one uppercase letter." 

# if @password_constraints[:contain] = ['one lowercase letter', 'one uppercase letter.'] 
message(@password_constraints) 
# => "Must be at least 6 character long. Must contain: one lowercase letter and one uppercase letter." 

# if @password_constraints[:contain] = ['one lowercase letter'] 
message(@password_constraints) 
# => "Must be at least 6 character long. Must contain: one lowercase letter" 
+0

Это, безусловно, больше похоже на Ruby. Для ясности предпочтительнее использовать оператор splat для вытягивания последнего элемента и использование интерполяции строк вместо конкатенации. Если вы действительно хотите напугать, вы можете изменить второй бит интерполированного кода в выходной строке на '' # {(другие << second_last) * ','} "', но это намного сложнее прочитать. –

+0

Такое элегантное решение и очень компактное. Это определенно то, что я искал. Спасибо огромное! – soutoner

+0

Я обновляю решение: вторая строка метода должна быть удалена, и она должна быть в конце третьего, чтобы не изменять текущий хеш. '* others, second_last, last = constraints [: содержать]' '' # {constraints [: length]} Должен содержать: # {(другие << second_last) .join (',')} "<<" и # {last} ", если last.nil?' – soutoner

-1

Here - забавный небольшой трюк в Ruby, который вы можете делать с массивами, чтобы вырезать необходимость в подробном join.

def password_constraints 
    @password_constraints[:length] << ' Must contain.' << @password_constraints[:contain] * ", " 
end 

* оператор Array класса явно проверяет наличие string второго операнда, а затем преобразует в вызов join под одеялом.

+0

Спасибо за информацию, в рубине много волшебства! hahah – soutoner

+2

Это приводит к ошибке и, даже исправлено, не добавляет «и» в финале – Doguita

0

Я использовал бы патч обезьяны здесь для лаконичности (да, мой метод join_requirements мог бы выглядеть немного лучше).

class Array 
    def join_requirements 
    result = "" 
    self.each do |requirement| 
     if requirement == self.last 
     result << "and " << requirement 
     else 
     result << requirement + ", " 
     end 
    end 
    result 
    end 
end 

Тогда в вашем коде вы видите только это:

contain = ['one number','one lowercase letter','one uppercase letter.'] 
puts contain.join_requirements 
# => one number, one lowercase letter, and one uppercase letter. 
+0

Большое вам спасибо за это решение, о котором я никогда не слышал раньше о патчах обезьян. Он работает отлично. Проблема в том, что в этом проекте мне нужно только это поведение для одного метода. Но в других проектах, где «и проблема» более частая, это будет лучшее решение! Еще раз спасибо. – soutoner

+0

Пока это работает, оно не является более компактным и не более «похоже на Ruby». –

+0

@theTinMan, это справедливо, я упомянул в ответ, что это не лучший способ написать его. Я просто хотел предложить исправление обезьян в качестве решения. –

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