是否有Ruby的数据库或数据结构来实现关系矩阵? [英] Is there a database or a data structure for Ruby to implement relation matrices?

查看:131
本文介绍了是否有Ruby的数据库或数据结构来实现关系矩阵?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的资料集

I've got a very simple data set


  • 产品

  • 属性

  • 交叉表:产品的属性相关性

  • products
  • attributes
  • cross table: attributes relevance for a product

                  red    blue   modern   old fashion  (50+ Entries)
     Jeans myway    0%   100%    30%       30%
     Polo Shirt   100%     0%    10%       40%
     (500+ Entries)


在应用程序中选择红色,蓝色等属性,按照相关性排序。

In the application you select the attribute like red, blue, .. and get the the products sorted by relevance.

存储数据的最佳方法是什么,ruby有好的数据结构(库)?

What's the best way to store the data, is there a good data structure (library) for ruby?

(不要告诉我如何使用传统的3个表sql和活动记录实现它。我已经知道如何,我正在寻找一个更好的解决方案。)

(Don't tell me how to implement it with traditional 3 tables sql and active record. I already know how. I'm looking for a better solution.)

一种方法是使用哈希:

"red" => {"Jeans myway" => 0, "Polo Shirt" => 100}, "blue" => {..

这是一个很好的方法,我应该如何存储到文件?

is this a good way and how should I store it to file?


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

[edit] Better solution: If I take a relational db, I've to split the matrix into 3 tables products, attributes, attributes_products. I would like to store it in one table / matrix and search / use it like a matrix.

例如。我想选择其中属性旧时尚,现代与相关性相关(> 0)的产品将返回Jeans myway 0.09,Polo Shirt 0.04。 (相关性通过乘法计算。)

E.g. I want to select products where the attributes 'old fashion', 'modern' are relevant (>0) sorted by relevance would return 'Jeans myway 0.09', 'Polo Shirt 0.04'. (Relevance is calculated by multiplication.)

推荐答案

这里有一个针对您的需求定制的解决方案。它允许您选择任意数量的产品或属性,并按照权重的乘积查看另一轴中的值。

Here's a solution tailored for your needs. It allows you to select an arbitrary number of products or attributes and see the values in the other axis sorted by the product of the weightings. It lets you store your data in CSV, so you can just keep a big Excel file of your grid for future tweaking.

merge_by

The merge_by, sort_by, and filter_by methods let you specify the block to be applied when getting your results.

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

这篇关于是否有Ruby的数据库或数据结构来实现关系矩阵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆