Функция, которая возвращает количество букв, повторяющихся в строке
Попытка создать функцию, которая подсчитывает количество букв, которые появляются более одного раза в любом месте строки (не обязательно вместе, а не количество повторений). Это то, что у меня есть:
def num_repeats(string)
repeat = []
i1 = 0
i2 = 1
while i1 < string.length
while i2 < string.length
if (string[i1] == string[i2]) && (!repeat.include? string[i1])
repeat << string[i1]
end
i2 +=1
end
i1+=1
end
return repeat.length
end
puts(num_repeats('sldhelanlaskjkajksda'))
По какой-то причине он только толкает первую букву строки, если эта первая буква была использована в остальной части строки, но после этого кажется, что метод останавливается, перейдя через остальную строку.
Сначала я хотел бы знать, почему текущий код не работает, и если есть способ его исправить, и я также приветствую другие лучшие решения.
Ответы
Ответ 1
Вот православный способ сделать это:
'sldhelanlaskjkajksda'.each_char.group_by(&:itself).count{|_, v| v.length > 1}
# => 6
Причина, по которой ваш код не работает, заключается в том, что (i) после того, как цикл i2
завершается, вы увеличиваете i1
и пытаетесь выполнить следующий цикл i2
в следующей итерации i1
, но поскольку i2
hasn ' t был затронут после того, как не удалось удовлетворить условию цикла, он не будет удовлетворять условию снова, и цикл i2
никогда не будет работать снова, и (ii) вы инициализируете i2
константу.
Чтобы исправить это, инициализируйте i2
внутри цикла i1
в начале и инициализируйте его до i2 = i1 + 1
, а не 1
.
Ответ 2
Другой способ:
s = 'sldhelanlaskjkajksda'
a = s.chars
#=> ["s", "l", "d", "h", "e", "l", "a", "n", "l", "a",
# "s", "k", "j", "k", "a", "j", "k", "s", "d", "a"]
a.difference(a.uniq).uniq.size
#=> 6
где Array#difference
определяется в моем ответе здесь.
Имеем:
b = a.uniq
#=> ["s", "l", "d", "h", "e", "a", "n", "k", "j"]
c = a.difference(b)
#=> ["l", "l", "a", "s", "k", "a", "j", "k", "s", "d", "a"]
d = c.uniq
#=> ["l", "a", "s", "k", "j", "d"]
d.size
#=> 6
Ответ 3
Ни один из этих ответов не считает, что ОП попросил повторить буквы
Но это делает:
'sldhe-lanlas-kjkajksda'.scan(/([a-z])(?=.*\1)/i).uniq.size
#=> 6
Ответ 4
Это решение для вашей проблемы
def num_repeats(string)
repeat = []
i1 = 0
i2 = 1
while i1 < string.length
while i2 < string.length
if (string[i1] == string[i2]) && !(repeat.include? string[i1])
repeat << string[i1]
end
i2 +=1
end
i1+=1
i2 = i1 + 1
end
return repeat.length
end
puts(num_repeats('sldhelanlaskjkajksda'))
Ответ 5
Вот немного проще (надеюсь) и немного Ruby-ish, решение:
def num_repeats(string)
# chars in string
chars = string.split('')
# initialize map - for each char, count is initialized to 0
hash = chars.uniq.inject({}) { |h, c| h[c] = 0; h}
# for each char in string, lets count its occurrences
chars.each do |c|
hash[c] += 1
end
# now lets pick those entries from the map where the count is > 1
hash_with_repeated_chars = hash.select {|k, v| v > 1 }
# now lets pick the chars that are repeated by picking keys of hash
repeated_chars = hash_with_repeated_chars.select { |k, v| k}
# return the count of repeated chars
return repeated_chars.count
end
p num_repeats('abc') # Prints 0
p num_repeats('abbc') # Prints 1
p num_repeats('abbcc') # Prints 2
p num_repeats('aabbcc') # Prints 3
У меня также есть версия Ruby, которая отличается от всех других ответов (и, следовательно, бит неэффективен из-за множества итераций, которые он делает внутри)
s = 'sldhelanlaskjkajksda'
p s.chars.combination(2).to_a.uniq.map(&:sort).map(&:uniq).select{|a| a.size.eql?(1)}.count