[英]Ruby counting duplicates in array and print into new file
我需要計算數組中重復項的數量,找出它們出現的次數,然后將其放入文檔中。.這就是我所做的,現在我不知道如何進行操作了。數據來自另一個txt文件。 如果這有點混亂,我深表歉意,但是我現在很困惑。
class Ticket
attr_accessor :ticknum
attr_accessor :serialnum
def initialize(ticknum,serialnum)
@ticknum = ticknum
@serialnum = serialnum
end
end
class Ticketbook
def initialize
@ticketbook = Array.new
end
def newticket(ticket)
@ticketbook << ticket
@ticketbook.sort! {|x,y| x.ticknum*1000 + x.serialnum <=> y.ticknum*1000 + y.serialnum}
end
def soldnumber(tickenum2,serialnum2)
@ticknum2 = ticknum2
@serialnumb2 = serialnum2
@antal = 0
for i in 0..@ticketbook.length-1
if @ticknum2 == @ticketbook[i].ticknum && @serialnum2 == @ticketbook[i].serialnum
@antal +=1
end
end
return @antal
end
end
ticketfile = File.open("tickets.txt", "r")
book = Ticketbook.new
ticketfile.each {|line|
a = line.split(",")
newdoc = Ticket.new(a[0].to_i,a[1].to_i)
book.newticket(newdoc)
}
registernums = File.new("registernums.txt", "w")
for i in (0..@ticketbook.length-1)
registernums.print book[i].@ticketnum.to_i + ", "
registernums.print book[i].@serialnumber.to_i + ", "
registernums.puts book[i].soldnumber(i)
end
print registernums
給我這個錯誤:rb 56意外的tIVAR,期望“(” registernums.print book [i]。@ ticketnum.to_i rb 57意外的tIVAR,期望“(” registernums.print book [i]。@ serialnum.to_i
您的for
循環沒有主體,因此您的最后幾行引用i
在未定義循環的外部。
問題在於這些行。
registernums.print book[i].@ticketnum.to_i + ", "
registernums.print book[i].@serialnumber.to_i + ", "
要訪問任何對象的實例變量,您無需放置@
。 所以正確的代碼應該是
registernums.print book[i].ticketnum.to_i + ", "
registernums.print book[i].serialnumber.to_i + ", "
就像@Jonah指出的那樣,應該在最后一個for循環的end
結束。
這里有一些問題:
for i in (0..@ticketbook.length-1)
registernums.print book[i].@ticketnum.to_i + ", "
registernums.print book[i].@serialnumber.to_i + ", "
registernums.puts book[i].soldnumber(i)
print registernums
該代碼在TicketBook
類之外,因此實際上沒有任何實例變量(以@
開頭的實例變量)。
如果要從TicketBook外部訪問票證陣列,請創建一個
attr_reader :ticketbook
在TicketBook
類中。
您可能想要用以下內容替換代碼:
book.ticketbook.each_with_index do |tb, i|
registernums.print tb.ticketnum.to_i + ", "
registernums.print tb.ticketnum.to_i + ", "
registernums.puts tb.soldnumber(i)
end
好家伙!
在開始一些重要說明之前:-您正在過度使用實例變量-票證類可以,但是Ticketbook(應為TicketBook)應僅具有一個instance_variable(在initialize方法中設置的一個),其余應位於方法作用域的局部。
Ruby的命名約定是用_分隔單詞(new_doc,ticket_file等)
您幾乎應該永遠不要使用for
循環-使用它的唯一原因是編寫自己的迭代器,但是您在此處作用於數組-請使用each
方法
現在,關於錯誤:
ticketfile = File.open("tickets.txt", "r")
book = Ticketbook.new
ticketfile.each {|line|
a = line.split(",")
newdoc = Ticket.new(a[0].to_i,a[1].to_i)
book.newticket(newdoc)
}
registernums = File.new("registernums.txt", "w")
for i in (0..@ticketbook.length-1) # @ticketbook is an instance variable of Ticketbook, you'll get undefined length for nil:NilClass
registernums.print book[i].@ticketnum.to_i + ", " # book is an instance of Ticketbook, [] is not defined on that class!
registernums.print book[i].@serialnumber.to_i + ", "
registernums.puts book[i].soldnumber(i)
print registernums
您的票務類
class Ticketbook
def initialize
@ticketbook = Array.new #personaly would prefer []
end
def newticket(ticket)
@ticketbook << ticket
@ticketbook.sort! {|x,y| x.ticknum*1000 + x.serialnum <=> y.ticknum*1000 + y.serialnum}
end
def soldnumber(tickenum2,serialnum2)
@ticknum2 = ticknum2 # unnecessary
@serialnumb2 = serialnum2 # unnecessary
@antal = 0
for i in 0..@ticketbook.length-1 # Should be @ticketbook.each do |ticket|
if @ticknum2 == @ticketbook[i].ticknum && @serialnum2 == @ticketbook[i].serialnum
@antal +=1
end
end
@antal
# much better would be:
# def soldnum(ticknum2, serialnum2)
# @ticketbook.select {|ticket| ticket.ticknum == ticknum2 && ticket.serialnum == serialnum }.count
# end
end
結束
我還將向您介紹group_by
方法-在數組上運行會將其轉換為一個非常漂亮的哈希,其中鍵是已執行塊的結果:
[1,2,3,4,5,6].group_by {|e| e.odd?} #=> {true => [1,3,5], false => [2,4,6]}
您可以使用它來一次性獲得重復計數:
# inside ticket book
def count_repetitions
Hash[@ticketbook.group_by {|e| [e.ticknum, e.serialnum]}.map {|key, value| [key, value.count]}
end
這應該返回哈希,其中鍵是包含ticknum和serialnum的兩個元素的數組,值是出現的次數
tIVAR
引用了一個實例變量,因此錯誤消息unexpected tIVAR
表示ruby在某處不期望使用實例變量,並且它指向此行(及其后的一行)
registernums.print book[i].@ticketnum.to_i + ", "
訪問對象中的屬性不使用@
字符(也不是變量名的一部分)。 訪問您的ticketnum
屬性的正確方法是
registernums.print book[i].ticketnum.to_i + ", "
回答完您的問題后,我想提出一種更“類似於Ruby”的方式來處理您的問題。 首先,幾點:
Ticket
類的實例,就像已經完成的那樣,由兩個元素組成的數組,但要理解的是,第一個和第二個元素分別對應於票證和序列號,或者使用一個鍵作為哈希值表示票號,另一個表示序列號。 我贊成哈希。 我認為不需要單獨的類,我認為使用數組更可能導致編碼錯誤(例如,如果您為票證或序列號使用了錯誤的數組元素)。 Enumerable
“ mixin”模塊中提供的所有方法,無需循環索引。 避免這種循環將使您的代碼更緊湊,更易於閱讀並且更不可能包含錯誤。 首先,向票務ticketbook
添加一些票證:
ticketbook = []
ticketbook << {tnbr: 22, snbr: 55}
ticketbook << {tnbr: 27, snbr: 65}
ticketbook << {tnbr: 22, snbr: 56}
ticketbook << {tnbr: 27, snbr: 66}
# => [{:tnbr=>22, :snbr=>55}, {:tnbr=>27, :snbr=>65}, \
{:tnbr=>22, :snbr=>55}, {:tnbr=>27, :snbr=>65}]
現在查找重復項(具有相同票證編號但序列號不同的票證)。 一旦您對Ruby有了更多的經驗,每當您想要按某個特征對數組的元素進行分組時,便會想到Enumerable#group_by
方法(或者可能是Enumerable#chunk
):
g0 = ticketbook.group_by {|t| t[:tnbr]}
# => {22=>[{:tnbr=>22, :snbr=>55}, {:tnbr=>22, :snbr=>56}], \
# 27=>[{:tnbr=>27, :snbr=>65}, {:tnbr=>27, :snbr=>66}]}
如您所見,當我們對票證編號進行group_by
時,我們將獲得一個包含元素(k,v)
的哈希,其中鍵k
是票證編號,值v
是具有該票證編號的票證(哈希)數組。
這可能就是您所需要的。 如果要對具有相同序列號的票證數量進行計數,可以使用Enumerable#map
將g0
哈希(具有相同票證號的票證數組)中的每個值轉換為此類票證的數量:
g1 = g0.map {|k,v| {k => v.size}} # => [{22=>2}, {27=>2}]
您可能會在這里停下來,但是如果這是一個哈希( {22=>2, 27=>2}
),而不是一個單對哈希數組,將會更加方便。 您可以通過多種方式將此數組轉換為哈希。 一種是使用map
將哈希值轉換為數組:
g2 = g1.map(&:to_a) # => [[[22, 2]], [[27, 2]]]
(其中map(&:to_a)
是map {|h| h.to_a}
簡寫),然后使用Array#flatten
將其轉換為:
g3 = g2.flatten # => [22, 2, 27, 2]
創建哈希的一種方法(通常)是這樣的:
Hash[1,2,3,4] # => {1=>2, 3=>4}
為此,我們需要在數組g3
上添加“ splat”運算符:
Hash[*g3] # => {22=>2, 27=>2}
這為我們提供了所需的按票號計數的哈希值。 我說過,這是將單對散列數組轉換為哈希的一種方法。 這是一種更直接的方法:
g1.pop.merge(*g1) # => {27=>2, 22=>2}
在這里, g1.pop
返回{27=>2}
並將g1
轉換為[{22=>2}]
。 因此,以上表達式等效於:
{27=>2}.merge(*[{22=>2}]) # => {27=>2, 22=>2}
它將散列數組中的哈希(此處僅是一個) merge
到merge
之前的哈希中。
通常不用“鏈接”這三個操作,而不必引入局部變量g0
和g1
:
ticketbook.group_by {|t| t[:tnbr]}.map {|k,v| {k => v.size}}.pop.merge(*g1)
# => {27=>2, 22=>2}
最后,雖然您的sort
版本很好,但是您也可以這樣:
ticketbook.sort! {|x,y| (x <=> y) == 0 ? x[:snbr] <=> y[:snbr] : \
x[:tnbr] <=> y[:tnbr]}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.