具有重复键值的哈希值

时间:2014-08-09 16:19:39

标签: ruby hash

我正在编写一个小脚本来检查文件夹中的重复文件。我做了数组,我成功了。问题是我也想存储文件夹位置,所以我可以看到重复文件的位置。

我的第一个想法是使用哈希。但是由于你在同一个文件夹中会有很多文件,我不能这样做:hash [folder] = file。反过来也是impossivel,因为如果我有重复文件,它们将被覆盖(hash [file] =文件夹)

那么最好的办法是什么?

我的代码:

class FilesList

 attr_accessor :elements

 def initialize(path)
    @elements = Hash.new
    @path = path
    printDirectory(@path)
 end

 def printDirectory(folderPath) 
 entries = Dir.entries(folderPath) - [".", "..", "repeat.rb"]
 entries.each do |single|
        if File.directory?("#{folderPath}/#{single}")
            printDirectory("#{folderPath}/#{single}")
        else
            @elements[single] = folderPath
        end
    end
 end

 def printArray
    puts @elements
 end

 def each()
    @elements.each do |x, y|
        yield x y
    end
end

def checkRepeated
    if @elements.length == @elements.keys.uniq.length
        puts "No repeated Files"
    else
        counts = Hash.new(0)
        @elements.each do |key,val|
            counts[val] += 1
        end
        repeateds = counts.reject{|val,count|count==1}.keys
        puts repeateds
    end
end

end

array = FilesList.new(Dir.pwd)

array.printArray

2 个答案:

答案 0 :(得分:1)

您可以将文件名(或文件夹路径)的数组(或sets)存储为哈希值

例如,在您的代码中,您可以将@elements[single] = folderPath更改为:

@elements[single] ||= []
@elements[single] << folderPath

然后,您的val将成为符合文件的文件夹数组。

答案 1 :(得分:0)

与上述类似,但不要将文件用作密钥。

@elements = Hash.new([])

entries.each do |single|
  if File.directory?("#{folderPath}/#{single}")
    printDirectory("#{folderPath}/#{single}")
  else
    @elements[folderPath] << single
  end
end

然后你会得到一些看起来像这样的东西:

{ '/path1' => ['awesome_file.rb', 'beautiful.js'],
  '/path2' => ['beautiful.js', 'coffee.rb'] }

然后,如果我理解正确,你可以找到如下的重复文件:

files = @elements.values.flatten
repeateds = files.select{ |file| files.count(file) > 1 }

这将返回一个数组:["beautiful.js", "beautiful.js"],您可以调用.uniq来获取["beautiful.js",或者根据需要进行计数,或将结果映射到另一个哈希,告诉你它重复的频率等等。