Лучший способ написать этот .map() на рубине?

У меня есть массив, который выглядит так: [[3, 1], 4, [3, 3, 4], 4, :sync, 1, 2]

Я хочу сопоставить массив и...

  • Если элемент является целым числом, замените его чем-то другим.
  • Если элемент представляет собой массив, замените только элемент с индексом 0 и верните массив

Это то, что у меня есть до сих пор, но это очень уродливо. Есть ли лучший способ написать это?

Может быть, я могу как-то использовать #tap?

work.map! do |w|
  if w.is_a? Array
    w[0] = console.button_map[w[0]] || w[0]
    w
  else
    console.button_map[w] || w
  end
end

person Tallboy    schedule 06.04.2015    source источник
comment
Вероятно, больше подходит для обмена стеками обзора кода.   -  person Dave Newton    schedule 06.04.2015


Ответы (3)


Я бы использовал Array() для нормализации ввода, а затем остался только случай:

work.map! do |w|
  element = Array(w).first
  console.button_map[element] || element
end
person spickermann    schedule 06.04.2015
comment
Или даже две отдельные карты: a.map { |e| Array(e).first }.map { |e| console.button_map[e] || e }. - person mu is too short; 06.04.2015
comment
Я не понимаю. Я понимаю element = Array(work).first (что, я думаю, вы могли бы также написать element = [*work].first), но если (аргумент) work является массивом, разве вы не сопоставляете его с некоторой функцией его первого элемента, а не сохраняете остальную часть? - person Cary Swoveland; 06.04.2015
comment
@CarySwoveland: Array(w) преобразует ввод в массив, если это уже не массив: Array(nil) #=> [], Array(:foo) #=> [:foo], но Array([:foo]) #=> [:foo] - person spickermann; 06.04.2015
comment
Хороший! Это потрясающая идея. - person Tallboy; 06.04.2015

Я остановился на этом, не уверен, что это может быть чище:

work.map! do |w|                                        
  if w.is_a? Array                                      
    w.tap{|x| x[0] = console.button_map[x[0]] || x[0] } 
  else                                                  
    console.button_map[w] || w                          
  end                                                   
end
person Tallboy    schedule 06.04.2015

work = [[3, 1], 4, [3, 3, 4], 4, :sync, 1, 2, [5]]

work.map! do |w|
  val = my_method [*w].first
  case w
  when Array then [val, *w[1..-1]]
  else val
  end
end

def my_method(n)
  case n
  when Fixnum then n+4
  else n.to_s
  end
end

work
  #=> [[7, 1], 8, [7, 3, 4], 8, "sync", 5, 6, [9]]

Примечание:

[*[1,2]] #=> [1,2]
[*3]     #=> [3]
person Cary Swoveland    schedule 06.04.2015