是否有Ruby的数据库或数据结构来实现关系矩阵?
我有一个非常简单的数据集
- 制品
- 属性
-
交叉表:产品的属性相关性
red blue modern old fashion (50+ Entries) Jeans myway 0% 100% 30% 30% Polo Shirt 100% 0% 10% 40% (500+ Entries)
在应用程序中,您可以选择红色,蓝色,…等属性,并获取按相关性排序的产品。
存储数据的最佳方法是什么,ruby有一个很好的数据结构(库)吗?
(不要告诉我如何使用传统的3表sql和活动记录来实现它。我已经知道了。我正在寻找更好的解决方案。)
一种方法可能是哈希:
"red" => {"Jeans myway" => 0, "Polo Shirt" => 100}, "blue" => {..
这是一个好方法,我应该如何将其存储到文件?
[编辑]更好的解决方案:如果我采用关系数据库,我将矩阵拆分为3个表产品,属性,attributes_products。 我想将它存储在一个表/矩阵中,并像矩阵一样搜索/使用它。
例如,我想选择产品,其中“旧时尚”,“现代”属性相关的属性(> 0)按相关性排序将返回’Jeans myway 0.09’,’Polo Shirt 0.04’。 (相关性通过乘法计算。)
这是针对您的需求量身定制的解决方案。 它允许您选择任意数量的产品或属性,并查看另一个轴中的值,这些值按权重的乘积排序。 它允许您以CSV格式存储数据,因此您可以保留网格的大型Excel文件以供将来调整。
merge_by
, sort_by
和filter_by
方法允许您指定获取结果时要应用的块。
TESTDATA = < [["Jeans myway", 9.0], ["Polo Shirt", 4.0]] p products.find( :row, 'Polo Shirt' ) #=> [["red", 100.0], ["old fashion", 40.0], ["modern", 10.0]] p products.find( :col, 'sexy' ) #=> [["Bra", 100.0], ["Jeans myway", 70.0], ["Polo Shirt", 1.0]] p products.find( :row, 'Polo Shirt','Bra' ) #=> [["red", 100.0], ["modern", 10.0]] p products.find( :col, 'sexy','modern' ) #=> [["Bra", 100.0], ["Jeans myway", 21.0], ["Polo Shirt", 0.1]] p products.find( :col, 'red', 'blue' ) #=> [] p products.find( :col, 'bogus' ) #=> [] end class RelationTable def self.load_from_csv( csv ) require 'csv' data = CSV.parse(csv) self.new( data.shift[1..-1], data.map{ |r| r.shift }, data ) end def initialize( col_names=[], row_names=[], weights=[] ) @by_col = Hash.new{|h,k|h[k]=Hash.new(0)} @by_row = Hash.new{|h,k|h[k]=Hash.new(0)} row_names.each_with_index do |row,r| col_names.each_with_index do |col,c| @by_col[col][row] = @by_row[row][col] = weights[r][c].to_f end end # Multiply all weights, sort by weight (descending), only include non-zero merge_by{ |values| values.inject(1.0){ |weight,v| weight*v/100 }*100 } sort_by{ |key,value| [-value,key] } filter_by{ |key,value| value > 0 } end def merge_by(&proc); @merge = proc; end def sort_by(&proc); @sort = proc; end def filter_by(&proc); @filter = proc; end def find( row_or_col, *names ) axis = (row_or_col == :row) ? @by_row : @by_col merge(axis.values_at(*names)).select(&@filter).sort_by(&@sort) end private # Turn an array of hashes into a hash of arrays of values, # and then merge the values using the merge_by proc def merge( hashes ) if hashes.length==1 hashes.first # Speed optimization; ignores the merge_by block else result = Hash.new{|h,k|h[k]=[]} hashes.each{ |h| h.each{ |k,v| result[k] << v } } result.each{ |k,values| result[k] = @merge[values] } result end end end test if __FILE__==$0