簡體   English   中英

迭代數組內的整數數字

[英]Iterate over digits of integers inside of array

我有以下代碼:

 a = [435,276,434]

 def product(a)
   final = 1
   for e in a
     for p in a[e]
       final*=p
     end
   end
   final
 end

 puts product(a)

我想知道如何迭代這個數組兩次,結果是4 * 3 * 5 = 60,2 * 7 * 6 = 85,和4 * 3 * 4 = 48

我在上面編寫了一些代碼,我認為這樣可以解決這個問題,但是Ruby一直在返回錯誤。

需要考慮以下幾點:

在Ruby中,你基本上不會使用for循環來迭代事物。 #each更好。 你可以通過一個街區,為你提供各種靈活性和表現力的空間。

此外,您不能 - 通常 - 迭代Integer 請記住,Integer是一個數值存儲,而不是特定的表示,因此它必須依賴於您想要的表示的基礎。 如果你想要一串字符,每個字符恰好都是數字,那么猜猜是什么? 你想要一個String ,就像這里的seph解決方案一樣。 或者一個Array ,這可能會更有意義,因為每個整數都將保持整數,並且不必來回解析。

告訴你什么,讓我們構建一個非常酷的方法來實現這一點並將其主要用於Integer,並希望展示Ruby的一些很酷的功能。

class Integer
  include Enumerable
  def each(base = 10, &blk)
    front, back = abs.divmod(base)
    if front > 0
      front.each(base, &blk)
    end
    yield back
  end
end

這個小數字取一個基數和一個塊,得到整數的絕對值(因為從技術上講,減號不是一個數字),然后用divmod分割數字,砍掉最后一個數字。 我們將這些碎片存放在前后。 我們檢查是否有更多的數字,由前面0表示,如果我們以遞歸方式調用此方法,則使用該塊。 然后我們只是屈服於后面,將數字發送到塊。

既然我們現在已經定義了each方法,我們現在可以自由地包含Enumerable ,它可以為我們提供大量的東西!

只要該修改處於活動狀態,您的product方法就變為:

(如果你想打印60 84 48): a.map {|n| n.reduce(:*)} a.map {|n| n.reduce(:*)}

(或者如果你想打印241920): a.reduce(:*).reduce(:*)

挺好的!

所以,這個完整的解決方案比seph的單行程要長一點,事實上,如果我需要實際做某些事情,我只會to_s 我的解決方案執行速度更快嗎? 誰知道? 但它肯定更具表現力,這就是你首先使用Ruby的原因。

如果你想解決問題,是的,絕對是, to_s 但是如果你希望你的代碼能夠表達一種關於數字的哲學,那么它們實際上也只是它們的集合 - 而且它們以一種奇怪的集理論方式,讓你能夠讓它成為那樣的。 而這種根本不需要字符串的方式,他們完全沒有勉強的幫助。 並且你可以迭代不同的基礎,如果你正在做十六進制或二進制,這是非常有用的,它保留了它們的更多數字本質。

在你和我一起建立的這個世界里,賈馬爾,小整數與大男孩一起穿過森林。 這太好了。

您可以將其轉換為字符串(.to_s)。 然后很容易將每個數字作為char(.chars),將它們轉換回整數(.map(&:to_i))並將它們相乘(.reduce(:*))

a = [435,276,434]
a.map {|n| n.to_s.chars.map(&:to_i).reduce(:*) }
=> [60, 84, 48] 

以下是修復代碼的一種方法:

a = [435,276,434]

def product(a)
  result = [] # Create an empty array that will become [60, 85, 48]
  for e in a
    final = 1
    # Convert the integer e to a string (e.g., "435")
    str = e.to_s
    # Iterate over each char of the string (e.g., "4", "3" and "5")
    str.each_char do |c|
      # Convert the character 'c' to an integer (digit) then multiply final by that integer          
      final *= c.to_i
    end    
    # Append the value of final to the result array
    result << final # e.g., when result = [60], result << 85 => [60, 85]
  end
  result # => [60, 85, 48]
end

product(a) # => [60, 85, 48]

現在讓我們看看我們如何改進它。 首先,我們可以鏈接操作並避免使用臨時變量str 此外,你會發現for循環, each通常都是優選for (特別是因為你可以使用each塊),所以我也會改變它。 雖然我在它,因為each_char循環只包含一個語句,我將用括號而不是do/end編寫塊。 我們現在有:

def product(a)
  result = [] # Create an empty array that will become [60, 85, 48]
  a.each do |e|
    final = 1
    e.to_s.each_char {|c| final *= c.to_i}
    result << final
  end
  result
end

當我看到這個時,我想我想將數組a每個元素轉換為其他東西(其數字的乘積)。 這表明使用了Array方法map! (或其同義詞, collect! ),而不是each 由於a是方法product的參數,如果我使用a.map! ,這將改變調用product的方法中a的值。 這可能也可能不行,但由於我正在返回計算值的數組,所以可能不行,所以我將應用map! 到副本a (它被稱為“淺層”副本,這在這里並不重要,但可以在其他情況下使用。)我們現在有:

def product(a)
  result = a.dup
  result.map! do |e|
    final = 1
    e.to_s.each_char {|c| final *= c.to_i}
    final
  end
  result
end

我們不需要最后的result ,因為map! 返回result (以及更改result )。 嘿,這也意味着我們可以只使用map (沒有區別)。 此外,我們可以鏈接a.dupmap來擺脫result

def product(a)
  a.dup.map do |e|
    final = 1
    e.to_s.each_char {|c| final *= c.to_i}
    final
  end
end

伙計,我們用煤氣做飯! 接下來,每當您看到計算產品或某事物總和的塊時,請考慮inject (或其同義詞, reduce ):

def product(a)
  a.dup.map do |e|
    e.to_s.each_char.inject(1) {|final, c| final * c.to_i}
  end
end

假設a <0怎么辦? (@Leon的回答讓我覺得這種可能性。)一個負面的接收者對each都沒有意義,所以如果發生這種情況,讓我們提出異常:

def product(a)
  raise RuntimeError, "Receiver must be non-negative" if self < 0
  a.dup.map do |e|
    e.to_s.each_char.inject(1) {|final, c| final * c.to_i}
  end
end

你可能想停在這里,但你可以用另一個`inject替換map

def product(a)
  raise RuntimeError, "Receiver must be non-negative" if self < 0
  a.inject([]) {|result, e| result.concat.e.to_s.each_char.inject(1) {|final, c| final * c.to_i}}
end

這里的注入參數是一個名為result的空數組。 請注意,由於我們沒有更改a ,因此我們不再需要dup (我看到@Kingston得到了類似的答案。)如果你願意,可以寫成:

def product(a)
  raise RuntimeError, "Receiver must be non-negative" if self < 0
  a.inject([]) {|result, e| result << e.to_s.each_char.inject(1) {|final, c| final * c.to_i}; result}
end

但請注意那個討厭的需要; result ; result結束了。

您可能會認為所有這些“改進”的最終結果是過於令人不安,或者作者只是炫耀。 這就是我剛認識Ruby時的想法。 但是,憑借經驗,您會發現它非常自然,讀起來像一個句子。 它還使調試更容易:從左到右工作,您可以測試鏈的每個鏈接,以確保它的工作。

a.collect{|x| 
  result = 1
  x.to_s.split('').each{|y| result *= y.to_i}
  result
}

如果意圖是迭代數字,您也可以使用字符串切片方法。

num = a[0].to_s # "435" 
final = num[0,1].to_i * num[1,1].to_i * num[2,1].to_i #4*3*5

要么

final = num[0..1].to_i * num[1..2].to_i * num[2..3].to_i

對於給定的問題,如果你知道它是一個3位數組,那么你可以跳過內循環,解決方案可能是這樣的:

a = [435,276,434]

def product(a)
    a.map! do |digits|
        final = 1
        num = digits.to_s
        final = num[0,1].to_i * num[1,1].to_i * num[2,1].to_i
    end
end

puts product(a).inspect

這個答案僅適用於上述問題。 由於它操縱相同的數組,因此它編輯接收器。 有關更詳細和完整的解決方案,請查看Cary Swoveland的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM