2017-03-01 4 views
-2

Ich möchte die Anzahl der verschiedenen Strings in verschiedenen Dateien erhalten. Eigentlich brauche ich zwei Arten von Zählungen. Für eine Zeichenfolge str,Anzahl der Strings mit Binary Search Tree in Ruby erhalten

1.) Gesamtzahl der Vorkommen der Zeichenfolge str in allen Dateien. 2.) Anzahl der Dateien mit der Zeichenfolge str.

Unten ist mein RUBY Code dafür, in dem ich es geschafft habe, die Gesamtzahl zu bekommen. Aber ich kann die Datei nicht zählen. Ich habe Arrays anstelle von Dateien zur Vereinfachung (analog zu Dateien) und eine Instanzvariable 'Flag' verwendet.

Mein Konzept ist, dass, wenn Flag = 0, bedeutet, dass die Zeichenfolge zum ersten Mal im ersten Array auftritt. Daher wird der Dateicount (oder Arraycount in diesem Fall) inkrementiert und flag wird auf 1 gesetzt. Wenn also dieselbe Zeichenfolge im selben Array erscheint, ist Flag bereits auf 1 gesetzt und nichts passiert. Wenn ein Array vorbei ist, werden alle Flag-Werte auf 0 gesetzt zurück (ich glaube so)

Aber etwas funktioniert nicht wie erwartet. Danke im Voraus..!

class Tree 
    attr_accessor :left 
    attr_accessor :right 
    attr_accessor :data 
    attr_accessor :count 
    attr_accessor :flag 
    attr_accessor :howmanyfiles 

    def initialize(x=nil) 
    @left = nil 
    @right = nil 
    @data = x 
    @count = 1 
    @flag = 0 
    @howmanyfiles = 1 
    end 


    def search(x) 
     if self.data == x 
     self.count = self.count + 1 
     if self.flag == 0 
      self.howmanyfiles = self.howmanyfiles + 1 
     end 
     return "#{self.data} found" #self 
     else 
     ltree = left != nil ? left.search(x) : nil 
     return ltree if ltree != nil 
     rtree = right != nil ? right.search(x) : nil 
     return rtree if rtree != nil 
     end 
    nil 
    end 


    def insert(x) 
    list = [] 

    if @data == nil 
    @data = x 
    self.flag = 1 
    elsif @left == nil 
    @left = Tree.new(x) 
    self.flag = 1 
    elsif @right == nil 
    @right = Tree.new(x) 
    self.flag = 1 
    else 
    list << @left 
    list << @right 
    loop do 
    node = list.shift 
    if node.left == nil 
     node.insert(x) 
     break 
    else 
     list << node.left 
    end 
    if node.right == nil 
     node.insert(x) 
     break 
    else 
     list << node.right 
    end 
    end 
    end 



    end 

    def traverse() 
    list = [] 
    yield @data 
    list << @left if @left != nil 
    list << @right if @right != nil 
    loop do 
    break if list.empty? 
    node = list.shift 
    yield node.data 
    list << node.left if node.left != nil 
    list << node.right if node.right != nil 
    end 
    end 






end 


    items = ["Amal","Hai", "Bob", "Bob", "Cat", "Cat", "Amal", "Dog", "Rizu", "Zol","Amal"] 

    tree = Tree.new 

    items.each {|x| 

    if tree.search(x) == nil 
     tree.insert(x) 
    end} 


    ObjectSpace.each_object(Tree) do |obj| 
     obj.flag = 0 
    end 

    items1 = ["Amal","wet", "jjj", "Cat"] 
    items1.each {|x| 

     if tree.search(x) == nil 
      tree.insert(x) 
     end} 



     ObjectSpace.each_object(Tree) do |obj| 
     obj.flag = 0 
     end 

     items2 = ["aa","Amal", "jjj"] 
     items2.each {|x| 

      if tree.search(x) == nil 
      tree.insert(x) 
      end} 

    ObjectSpace.each_object(Tree) do |obj| 
    puts obj.data.to_s + " " + obj.count.to_s + " " + obj.howmanyfiles.to_s 
    end 

    tree.traverse {|x| print "#{x} "} 
    print "\n" 

OUTPUT - in Format String TOTAL_COUNT ArrayCount

aa 1 1 
jjj 2 2 
wet 1 1 
Zol 1 1 
Rizu 1 1 
Dog 1 1 
Cat 3 2 
Bob 2 2 <--Bob is only present in first array but still output says 2. 
Hai 1 1 
Amal 5 3 
Amal Hai Bob Cat Dog Rizu Zol wet jjj aa 
+0

Was ist der Fehler, den Sie stoßen? Könnten Sie den Stack-Trace oder die Ausgabe des Programms im Gegensatz zur erwarteten Ausgabe teilen? – Sinstein

+0

Meine Anzahl für die Anzahl der Arrays mit der Zeichenfolge Bob ist falsch. Wie Sie sehen können, hat nur ein Array Bob, aber die Anzahl der Ausgabelisten beträgt 2. –

+1

Einrückung hier ist ein wenig durcheinander. Versuchen Sie, Ihren Code so strukturiert wie möglich zu halten, wenn Sie Fragen stellen, da Klarheit hilft, die Absicht zu kommunizieren. – tadman

Antwort

0

Die Frage aus den ersten beiden Absätzen scheint klar zu sein, aber ich kann nicht verstehen, wie ein binärer Suchbaum zum Vorteil verwendet werden könnte. Meine Lösung ist ein direkter Ansatz, um die gewünschten Zahlen zu erhalten.

-Code

def get_counts(filenames, target) 
    filenames.each_with_object([0, 0]) do |fname, arr| 
    n = File.read(fname).scan(/#{target}/).size 
    next if n.zero? 
    arr[0] += n 
    arr[1] += 1 
    end 
end 

wo files ein Array von Dateinamen und target ist die Zeichenfolge wir suchen.

Beispiel

die Dateien, indem 3-Test Lassen Sie starten.

filenames = ['file1', 'file2', 'file3'] 
text  = ["Hoya, Bob. Your bro's name is Bob too. Eh?", 
       "I gotta go feed my cat", 
       "A girl named Bob?"] 

filenames.zip(text).each { |fname, str| File.write(fname, str) } 

Bestätigen Sie die Dateien geschrieben wurden:

filenames.map { |fname| File.read(fname) } 
    #=> ["Hoya, Bob. Your bro's name is Bob too. Eh?", 
    # "I gotta go feed my cat", 
    # "A girl named Bob?"] 

Angenommen, wir suchen die Zeichenfolge

target = 'Bob' 

Dann

tot, files = get_counts(filenames, target) 
    #=> [3, 2] 
tot 
    #=> 3 
files 
    #=> 2 
+0

Danke für deine Antwort @Cary. Aber ich habe Zweifel. Ich muss diesen Suchvorgang für jede Zeile (String) in etwa 1000 Dateien mit jeweils mehr als 20.000.000 Zeilen durchführen. Ich habe versucht, eine normale lineare Suche zu machen, aber es braucht viel Zeit. Also wurde ich gebeten, einen binären Suchbaum zu verwenden, um die Zeit zu verkürzen. Also, welcher Algorithmus verwendet die Scan-Methode in Ruby? Oder gibt es einen effizienten Weg, wie ich diese Sache erledigen kann? –

+0

Da ich nicht wusste, dass Sie mit großen Dateien zu tun hatten, habe ich jede Datei mit [IO # read] (http://ruby-doc.org/core-2.3.0/IO.html#method-i-read) in einen String geschluckt. . Bei so großen Dateien würde man die Datei Zeile für Zeile lesen (z. B. mit [IO # for_each] (http://ruby-doc.org/core-2.3.0/IO.html#method-c-foreach))). Mein Code würde sich sehr wenig ändern. Sie würden [String scan] (http://ruby-doc.org/core-2.3.0/String.html#method-i-scan) auf jede Zeile anwenden und diese Summe über alle Zeilen addieren ... (Forts.) .) –

+0

... Meine Antwort ist für die Suche nach Strings, nicht nach Wörtern oder Substrings von Wörtern (weil das nicht Teil der Spezifikation der Frage war). Wenn Sie Wörter möchten, müssen Sie die Dinge anders machen (z. B. einen regulären Ausdruck mit Wortgrenzen verwenden). Wenn Sie zum Beispiel nach dem Wort "cat" gesucht haben, aber nur nach dieser Zeichenfolge gesucht haben, werden "catsup", "catch" usw. gezählt. (Forts.) –