2017-03-01 3 views
-2

다른 파일에 저장된 다양한 문자열의 수를 얻고 싶습니다. 실제로 저는 두 가지 유형의 카운트가 필요합니다. 문자열 str의 경우Ruby에서 이진 검색 트리를 사용하여 문자열 수를 계산하시오

1) 모든 파일에 대해 문자열 str이 발생하는 총 횟수입니다. 2.) 문자열 str을 가진 파일의 수.

아래는 내 RUBY 코드로 총 개수를 관리했습니다. 하지만 파일 수를 가져올 수 없습니다. 나는 단순함 (파일과 유사)과 인스턴스 변수 'flag'대신에 파일 대신에 배열을 사용했다.

내 개념은 flag = 0이면 첫 번째 배열에서 처음으로 문자열이 발견된다는 것입니다. 따라서 filecount (또는이 경우에는 arraycount)가 증가하고 flag는 1로 설정됩니다. 따라서 동일한 문자열이 동일한 배열에 나타나면 flag는 이미 1로 설정되고 아무 것도 발생하지 않습니다. 배열이 끝나면 이 모든 플래그 값이 0 다시 설정

을 (난 그렇게 생각)하지만 예상대로 뭔가가 작동하지 않습니다. 미리 감사드립니다 ..!

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 - 문자열의 형식이 문제는 처음 두 단락에서 분명한 것 같다

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

target = 'Bob' 

찾는거야? 예상 출력과 달리 프로그램의 스택 추적 또는 출력을 공유 할 수 있습니까? – Sinstein

+0

문자열 Bob이있는 배열 개수가 잘못되었습니다. 보시다시피, 하나의 배열에만 Bob이 있지만 출력 목록 개수는 2입니다. –

+1

들여 쓰기는 다소 엉망입니다. 명확하게 의사 소통의 의사를 전달하는 데 도움이되도록 질문 할 때는 가능한 한 체계적으로 코드를 작성하십시오. – tadman

답변

0

ArrayCount TOTAL_COUNT,하지만 난 이진 검색 트리를 유리하게 이용 될 수 있는지 이해할 수 없습니다. 내 솔루션은 원하는 카운트를 얻기 위해 어려운 접근 방식입니다.

코드

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 
files은 파일 이름의 배열입니다

target 우리가 찾고있는 문자열입니다.

는의 3 개 테스트 파일을 만들어 시작하자.

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) } 

확인 파일이 기록 된 :

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?"] 

생각에는 우리는 문자열 오류가 무슨 발생한되는 그런

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

답장을 보내 주셔서 감사합니다. @Cary. 하지만 몇 가지 의구심이 있습니다. 각각 20,00,000 + 라인을 가진 약 1000 개 이상의 파일에있는 모든 라인 (문자열)에 대해이 검색 프로세스를 수행해야합니다. 정상적인 선형 검색을 시도했지만 많은 시간이 걸립니다. 그래서 나는 시간을 단축하기 위해 이진 탐색 트리를 사용하도록 요청 받았다. 그래서 루비에서 스캔 방법은 어떤 알고리즘을 사용합니까? 또는이 일을 처리 할 수있는 효율적인 방법이 있습니까? –

+0

대용량 파일을 다루고 있다는 것을 모르는 상태에서 [IO # read] (http://ruby-doc.org/core-2.3.0/IO.html#method-read)를 사용하여 각 파일을 문자열로 꿀꺽 꿀꺽했습니다. . 큰 파일의 경우 줄 단위로 파일을 읽습니다 (예 : [IO # for_each] (http://ruby-doc.org/core-2.3.0/IO.html#method-c-foreach)). 내 코드는 거의 변하지 않을 것입니다. [String # scan] (http://ruby-doc.org/core-2.3.0/String.html#method-i-scan)을 각 행에 적용하고 모든 행에 대해 합계를 합계합니다 (cont .) –

+0

... 내 대답은 문자열이나 단어의 하위 문자열이 아닌 문자열을 검색하는 것입니다 (질문의 스펙에 포함되지 않았기 때문에). 단어를 원하면 다른 방식으로 작업해야합니다 (예 : 단어 경계가있는 정규 표현식 사용). 예를 들어 "고양이"라는 단어를 검색했지만 해당 문자열을 검색 한 경우 "고양이", "잡기"등은 계산됩니다 .... (계속) –