Решение 99 проблем Лисп, p09 в Ruby


Я довольно новыми для Ruby, и я боюсь, что мое решение задачи 9 из 99 сюсюкать проблемы является чрезвычайно запутанным и неэффективным. Проблема:

enter image description here

Мой Код

ul = "putanytexthere"
h = []

ul.upcase
  .split('')
  .sort
  .join('')
  .each_char
  .slice_when { |a,b| a != b }
  .map(&:join)
  .each do |el|
    if el.length > 1
      h << el
    end
  end

  print h.length


116
1
задан 21 февраля 2018 в 06:02 Источник Поделиться
Комментарии
2 ответа

Во-первых, пару код стиля вещи:


  • Логика, как это лучше всего помещенный в способ

  • Метод длинной цепи, как это лучше разбить на логические части, для лучшей читабельности.

Так, я пойду шаг за шагом с изменениями в коде. Во-первых, оформить его в виде метода:

def pack_duplicates(ul)
h = []

ul.upcase
.split('')
.sort
.join('')
.each_char
.slice_when { |a,b| a != b }
.map(&:join)
.each do |el|
if el.length > 1
h << el
end
end

return h
end

puts pack_duplicates("putanytexthere").length

Затем перерыв, что длинная цепочка на логические части:

def pack_duplicates(ul)
h = []

chars = ul.upcase.split('').sort
# You called #join on this and #each_char, but #each_char
# basically just undoes #join, so we can eliminate both.
groups = chars.slice_when { |a,b| a != b }.map(&:join)
groups.each do |el|
if el.length > 1
h << el
end
end

return h
end

puts pack_duplicates("putanytexthere").length

И, наконец, когда вы видите каждую петлю, которая формирует массив, который обычно означает, что #each можно заменить #map:

def pack_duplicates(ul)    
chars = ul.upcase.split('').sort
groups = chars.slice_when { |a, b| a != b }.map(&:join)
final = groups.map do |el|
[el[0], el.length]
end.to_h
end

puts pack_duplicates("putanystringhere")

В #map звоните выше, я внесла некоторые изменения в свой оригинальный выход. Вместо создания массива, я сгенерированный хэш в формате {<char> => <number of occurances>}. Это делает более логический смысл для меня, чем ваш выход. (Чтобы получить ваш выход, вы можете позвонить pack_duplicates("somestr").count { |_char, count| count > 1 })

Кроме того, ваш код выводит число-длина выходного массива, в то время как вызов мандатов, что, кажется, вложенного массива. Это вложенный массив на выходе #slice_when линии, так что я не совсем понимаю, что происходит после этого.

1
ответ дан 21 февраля 2018 в 07:02 Источник Поделиться

Вот решение, которое направлено на решение описанной проблемы.

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

require 'minitest/autorun'

class L99
# P09 (**) Pack consecutive duplicates of list elements into sublists.
# If a list contains repeated elements they should be placed in separate sublists.
def self.pack(list)
list.slice_when { |i, j| i != j }.to_a
end
end

class PackTest < Minitest::Test
def test_pack
list = %i[a a a a b c c a a d e e e e]
expected = [%i[a a a a], [:b], %i[c c], %i[a a], [:d], %i[e e e e]]

assert_equal expected, L99.pack(list)
end

def test_pack_string
str = 'putanytexthere'
expected = [['a'], %w[e e e], ['h'], ['n'], ['p'], ['r'], %w[t t t], ['u'], ['x'], ['y']]

assert_equal expected, L99.pack(str.each_char.sort)
end
end

2
ответ дан 27 февраля 2018 в 07:02 Источник Поделиться