Удалить конечные значения nil из массива в ruby
У меня есть массив вроде этого:
[["a", nil, nil, nil], ["b", nil, "c", nil], [nil, nil, nil, nil]]
Я хочу удалить все конечные значения nil из массива в ruby.
Я пробовал arr.map {|x| x.pop until x.last}
, но проблема с этим подходом заключается в том, что когда все значения массивов равны нулю, как в 3-м массиве в заданном массиве, цикл завершается.
Из-за условия until x.last
, если все значения равны nil, тогда функция map должна вернуть мне пустой массив?
Какими должны быть условия для этого.
Выход должен быть
[['a'],['b','nil','c'],[]]
Помните, что я просто хочу удалить конечные значения nil
, не находящиеся между ними.
Ответы
Ответ 1
Для этого вы можете забыть о внешнем массиве и решить его только для внутренних массивов, а затем использовать map
для применения решения для всех них.
drop_while
вернет новый массив без всех ведущих элементов, которые удовлетворяли некоторому условию (например, nil?
). Вы хотели, чтобы трейлинг сочетался с reverse
.
[nil,nil,5,nil,6,nil].reverse.drop_while(&:nil?).reverse
[nil, nil, 5, nil, 6]
Затем используйте карту для всех массивов.
arr = [["a", nil, nil, nil], ["b", nil, "c", nil], [nil, nil, nil, nil]]
arr.map{|a| a.reverse.drop_while(&:nil?).reverse}
[["a"], ["b", nil, "c"], []]
Если вы хотите, чтобы оставшаяся nil
фактически была строкой, вы можете объединить ее с другой картой, выполняющей любое такое преобразование, которое вам нравится.
Ответ 2
Вы на правильном пути, но немного измените свой код:
array.each { |e| e.pop until !e.last.nil? || e.empty? }
#=> [["a"], ["b", nil, "c"], []]
Это быстрее, чем использование reverse
- reverse
и drop_while
.
Ответ 3
Еще один вариант - использовать rindex
:
arr.map do |e|
index = e.rindex { |i| !i.nil? } # the last index of not `nil` element
index ? e.first(index + 1) : e
end
#=> [["a"], ["b", nil, "c"], []]