2017-05-06 69 views
-1

我正試圖編寫一個方法來檢查我們是否在字符串中多次看到一個元素。這段代碼返回字符串,但不是布爾值---我不認爲它甚至返回正確的字符串!(Ruby)方法來檢查元素是否已經出現

任何人都可以建議嗎?

def repeating_letters?(str) 
    # downcase the whole str 
    # create a "seen letters" array 
    # iterate through each char in array 
    # if seen letters contains that character, return true 
    down = str.downcase 
    seen = [] 
    down.each_char do |index| 
    if seen.include?(index) 
     TRUE 
    else 
     seen << index 
    end 
    end 
end 

p repeating_letters?("aA") 
+1

應該'repeating_letters( 「AA」)''回報或TRUE''FALSE'? – Stefan

+0

'str.each_char.with_object(Hash.new(0))。any? {| c,h | h [c] + = 1; h [c] == 2}' – aqfaridi

+0

這個問題是重複副本的副本。公平地說,接受的答案是無效的。 –

回答

2

的問題在你的代碼是你浪費true,順便downcase,你不使用它。目前還不清楚你想要做什麼。我希望seen是一個散列。

def repeating_letters?(str) 
    str.downcase.chars.group_by(&:itself).values.any? { |a| a.size > 1 } 
end 

itself可從紅寶石2.3.0,否則

def repeating_letters?(str) 
    str.downcase.chars.group_by { |c| c }.values.any? { |a| a.size > 1 } 
end 
+0

不幸的是,代碼必須在檢測到重複之前處理字符串中的每個字符。 – Stefan

+0

是的,我知道。如果你有一個大字符串,這不太好。 – Ursus

+0

你可以使用'lazy'解決這個問題:http://patshaughnessy.net/2013/4/3/ruby-2-0-works-hard-so-you-can-be-lazy – coreyward

0

你可以這樣做:

def check(str) 
    repeated = false 
    str.downcase.split.uniq.each { |i| repeated = true and break if str.count(i) > 1 } 
    repeated 
end 
0
def repeating?(str) 
    str.downcase! 
    seen = {} 
    str.each_char.with_index do |char, index| 
    if index !=0 && str[0..(index-1)].include?(char) 
     seen[char] = seen[char].nil? ? 2 : seen[char]+=1 
    end 
    end 
    seen 
end 

輸出

> p repeating?("peEterr") 
{"e"=>3, "a"=>2} 
+0

這是真的*對長字符串慢,爲什麼它是值得的。如果你想獲得每個角色的數量,你最好使用[count](http://ruby-doc.org/core-2.4.1/String.html#method-i-count)。 – coreyward

3

爲此,您可以輕鬆了不少:

def repeated_characters?(s) 
    !! s =~ /(.)\1/ 
end 

沒有陣列,通過琴絃沒有循環,沒有票,只是一個簡單的正則表達式匹配任何字符後面是相同的字符。

或者,如果你不關心鄰居,你可以這樣做:

Set.new(s.chars).length == s.length 

# or this: 

s.each_char.uniq.length == s.length 
+0

具有捕獲組和反向引用的正則表達式是否意味着數組,循環和計數? ;-) – Stefan

+0

@Stefan如果你想擔心Oniguruma的實現細節是我的客人,但是不...反向引用正在看前一場比賽。這是一個窗口掃描操作。 – coreyward

+2

如果重複的字符必須彼此相鄰(我不認爲是這種情況,部分來自問題的標題),另一種方式是's.squeeze == s'。 –

2

您的代碼不起作用,因爲String#each_char返回接收者,即字符串。你必須使用一個明確的return代替:(我已經修正了一些小問題,太)

def repeating_letters?(str) 
    seen = [] 
    str.downcase.each_char do |char| 
    if seen.include?(char) 
     return true   # <- you need a `return` here 
    else 
     seen << char 
    end 
    end 
    return false    # <- last statement, so `return` is optional 
end 

或者你可以使用any?返回true如果塊永遠返回true(和false其他):

def repeating_letters?(str) 
    seen = [] 
    str.downcase.each_char.any? do |char| 
    if seen.include?(char) 
     true 
    else 
     seen << char 
     false 
    end 
    end 
end 

這可以通過使用一個散列被短路到計數字符:

def repeating_letters?(str) 
    seen = Hash.new(0) 
    str.downcase.each_char.any? { |char| (seen[char] += 1) == 2 } 
end 

在該塊內,char的散列值增加1,並與2進行比較,該值表示字符之前是否出現過。

我還從方法移動downcase給調用者,使代碼更通用的:

​​
+0

您的最後一種方法很短,可讀性強,應儘快返回。 –

相關問題