首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ruby是否有数据库或数据结构来实现关系矩阵?

Ruby是否有数据库或数据结构来实现关系矩阵?
EN

Stack Overflow用户
提问于 2011-03-29 19:31:27
回答 1查看 218关注 0票数 1

我有一个非常简单的数据集

  • products
  • attributes
  • cross表:产品的属性相关性

红蓝色现代旧式时装(50+ )牛仔裤0% 100% 30% 30% Polo衬衫100% 0% 10% 40% (500+条目)

在应用程序中,您选择属性如红色、蓝色、..把产品按相关性排序。

存储数据的最佳方法是什么,对于ruby是否有一个良好的数据结构(库)?

(不要告诉我如何用传统的3表sql和active record实现它。我已经知道怎么做了。我正在寻找一个更好的解决方案。)

一种方法可能是使用哈希:

代码语言:javascript
复制
"red" => {"Jeans myway" => 0, "Polo Shirt" => 100}, "blue" => {..

这是一种好方法吗?我应该如何将它存储到文件中呢?

编辑更好的解决方案:如果采用关系数据库,我必须将矩阵分解为3个表--产品、属性、attributes_products。我想把它存储在一个表/矩阵中,并像矩阵一样搜索/使用它。

例如,我想选择的产品属性‘旧时尚’,‘现代’相关(>0)排序的相关性将返回'Jeans myway 0.09','Polo恤0.04‘。(相关性由乘法计算。)

EN

Stack Overflow用户

回答已采纳

发布于 2011-03-29 23:00:44

以下是为您的需求量身定做的解决方案。它允许您选择任意数量的产品或属性,并查看按权重乘积排序的另一个轴中的值。它允许您将数据存储在CSV中,因此您只需保留网格的一个大Excel文件,以便将来进行调整。

merge_bysort_byfilter_by方法允许您在获取结果时指定要应用的块。

代码语言:javascript
复制
TESTDATA = <<ENDCSV
,red,blue,modern,old fashion,sexy
Jeans myway,0%,100%,30%,30%,70%
Polo Shirt,100%,0%,10%,40%,1%
Bra,100%,0%,100%,0%,100%
ENDCSV

def test
  products = RelationTable.load_from_csv( TESTDATA )

  p products.find( :col, 'old fashion','modern' )
  #=> [["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
票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5477874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档