Нужен метод `values_at_if` для отображения значений в ruby - PullRequest
0 голосов
/ 25 марта 2019

У меня есть два массива одинакового размера

response = ["N","N","Y","Y","Y"]
mapping = ["A","B","C","D","E"]

Мне нужно выбрать элементы в mapping, чье соответствующее значение в response, то есть элемент с таким же индексом, равен "Y", как показано ниже

["C","D","E"]

Это напоминает мне метод values_at. Мое решение заключается в следующем

def values_at_if(response, mapping)
    result=[]
     response.each_index |k|
       if k=="Y"
         result << mapping[k]
       end
     end
   result
end

Я не доволен этим. Пожалуйста, дайте мне знать, как сделать это эффективно.

Ответы [ 4 ]

4 голосов
/ 25 марта 2019

Обновление

Самое простое решение, которое я могу придумать, это:

mapping.select.with_index {|_,i| response[i] == "Y"}
#=>["C", "D", "E"]

Это будет select всех элементов в mapping, где соответствующий индекс в response равен "Y"

TL; DR Другие опции включают в себя:

mapping.values_at(*response.each_with_index.select {|v,_| v == "Y"}.map(&:last))


mapping.zip(response).map {|k,v| k if v == "Y"}.compact

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

[["N",0],["N",1],["Y",2],["Y",3],["Y",4]]

Затем мы выбираем группы, в которых первый элемент равен "Y", и сопоставляем индексы для передачи на values_at

Во второй версии создается сопоставление и ответ, создавая вместе.

[["A", "N"], ["B", "N"], ["C", "Y"], ["D", "Y"], ["E", "Y"]]

Тогда сопоставьте первый элемент только тогда, когда второй элемент "Y". Compact удаляет значения nil из сопоставления.

Существует множество других способов выполнить эту задачу, если вы посмотрите модуль Enumerable

3 голосов
/ 25 марта 2019

Преобразовать response в Перечислитель; each без блока делает это. Затем используйте его в блоке выбора. Если блок возвращает true, то элемент выбран:

response = ["N","N","Y","Y","Y"]
mapping  = ["A","B","C","D","E"]

enum_resp = response.each
mapping.select{ enum_resp.next == "Y" } # =>["C", "D", "E"]

Обратите внимание, что это сэкономит память, если response будет состоять из false и true с, что также сделает ненужным сравнение в блоке выбора.

3 голосов
/ 25 марта 2019

Я бы пошел с

mapping.zip(response).select { |_, r| r == 'Y' }.map(&:first)
#=> ["C", "D", "E"]
1 голос
/ 25 марта 2019
response.each_with_object([]).with_index do |(v, arr), i|
  arr << mapping[i] if v == 'Y' 
end

Или

mapping.each_with_object([]).with_index do |(v, arr), i|
  arr << v if response[i] == 'Y' 
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...