Добавьте s в конец каждого слова в массиве, кроме 2-го элемента в данном массиве, используя только одну строку кода.

У меня есть массив строк из одного слова, и я хотел бы добавить «s» в конец каждой строки из одного слова, за исключением второй строки (элемента) в массиве. Я могу легко сделать это, используя 9 строк кода, но предпочел бы сделать это с помощью 3 строк кода.

Вот мой рабочий код, использующий 9 строк.

def add_s(array)
    array.each_with_index.collect do |element, index|
        if index == 1
            element
        else element[element.length] = "s"
            element
        end
    end
end

Вот мой сломанный код, когда я пытаюсь использовать только 3 строки.

def add_s(array)
    array.each_with_index.map {|element, index| index == 1 ? element : element[element.length] = "s"}
end

Наверху вернется...

array = ["hand", "feet", "knee", "table"]
add_s(array) => ["s", "feet", "s", "s"]

Я пытаюсь получить...

array = ["hand", "feet", "knee", "table"]
add_s(array) => ["hands", "feet", "knees", "tables"]

person BavarianRhino    schedule 24.12.2018    source источник
comment
Почему вы хотите добавить "s" к этим словам? А почему вы хотите пропустить второе слово в списке? Это похоже на проблему xy для меня. Вы стремитесь использовать слова во множественном числе? А ты понял, что там нет ног? Пожалуйста, уточните это. Поскольку правило множественного числа более сложное, что, если бы в списке были такие слова, как осьминог или человек?   -  person spickermann    schedule 24.12.2018
comment
Можете ли вы объяснить, почему вам нужно сделать это в 1 строку? Между прочим, это совершенно тривиально, так как в Ruby разрывы строк необязательны. Просто возьмите свои 9 строк кода и удалите разрывы строк, тогда у вас будет 1 строка кода.   -  person Jörg W Mittag    schedule 25.12.2018


Ответы (5)


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

Здесь метод для всех индексов (кроме 1) возвращает "s", потому что это то, что возвращает блок:

foo = "bar"
foo[foo.length] = "s"
#⇒ "s"

Если вы позже проверите свой массив mutated, вы увидите, что он был успешно изменен в соответствии с вашими пожеланиями.

input = %w[hand feet knee table]
def add_s(input)
  input.each_with_index.map do |element, index|
    index == 1 ? element : element[element.length] = "s"
  end
  input # ⇐ HERE :: return the mutated object
end
#⇒ ["hands", "feet", "knees", "tables"]

или, что еще проще, не отображать, а просто повторять и видоизменять:

input = %w[hand feet knee table]
def add_s(input)
  input.each_with_index do |element, index|
    element[element.length] = "s" unless index == 1
  end
end

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

def add_s(input)
  input.each_with_index.map do |element, index|
    index == 1 ? element : element + "s"
  end
end
#⇒ ["hands", "feet", "knees", "tables"]

Если бы мне дали такую ​​задачу, я бы также вел список элементов, которые нужно пропустить, так как рано или поздно их будет больше одного:

input = %w[hand feet knee scissors table]
to_skip = [1, 3]
def add_s(input)
  input.each_with_index.map do |element, index|
    next element if to_skip.include?(index)
    element + "s"
  end
end
#⇒ ["hands", "feet", "knees", "scissors", "tables"]
person Aleksei Matiushkin    schedule 24.12.2018

["hand", "feet", "knee", "table"].map.with_index{|v,i| i==1 ? v : v + 's'}
#=> ["hands", "feet", "knees", "tables"]

map.with_index помогает.
В основном map.with_index равно each_with_index.collect.
each с collect (так же, как map) не нужны.

Если вы хотите изменить исходный массив, вы можете изменить + на <<, но не рекомендуется.

person Tiw    schedule 24.12.2018

Я предлагаю выполнить следующие действия в соответствии с предоставленными словами,

arr = ['apple', 'knee', 'crab', 'jails']
arr.each_with_index.map { |x,i| i == 1  ? x : x + 's' }
=> ["apples", "knee", "crabs", "jailss"]

но чтобы избежать нежелательных дополнительных 's' в конце строк,

arr = ['apple', 'knee', 'crab', 'jails']
arr.each_with_index.map { |x,i| i == 1 || x[-1] == 's' ? x : x + 's' }
=> ["apples", "knee", "crabs", "jails"]
person ray    schedule 24.12.2018

Разрывы строки в Ruby совершенно необязательны, их всегда можно заменить ключевым словом, точкой с запятой, а иногда и вовсе убрать. Таким образом, всегда можно написать любую программу на Ruby, какой бы сложной она ни была, в одну строку.

Вот ваш код в одну строку:

def add_s(array) array.each_with_index.collect do |element, index| if index == 1 then element else element[element.length] = "s"; element end end end

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

person Jörg W Mittag    schedule 25.12.2018

Этого легко добиться с помощью «active_support».

arr = ["hand", "feet", "knee", "table"]

2.0.0-p648 :023 > require 'active_support/inflector'
 => true

arr.map { |a| arr.index(a) == 1 ? a : a.pluralize }
 => ["hands", "feet", "knees", "tables"]
person Dyaniyal Wilson    schedule 24.12.2018
comment
В ядре Ruby нет active_support. - person Aleksei Matiushkin; 24.12.2018
comment
метод множественного числа ActiveSupport не просто добавляет "s" в конец строки. - person spickermann; 24.12.2018