关于如何设计数据结构的建议

时间:2011-11-21 17:45:56

标签: python algorithm data-structures

我有一个文件,我正在从中读取数据。 我需要有关如何设计数据结构的建议,该结构执行以下操作: 所以,数据的形式是

id_1::id_2::similiarity_score

现在,虽然数据采用这种形式,但也意味着

id_2::id_1::same_similiarity_Score

所以,我想要的是一个数据结构,当我在程序中使用时。 所以我想说我想使用这些数据来找到哪两个相似的项目

object.maxSimiliarity(object_id_1)
returns object_id_2 # has max score

但是这个object_id_1也可以在数据库的product_id_2列中...

所以在数据库中可以是以下形式之一:

 object_id_1:: object_id_2::score
 or object_id2::object_id_1::score

所以我想要以

的方式设计这个数据结构
k_1, k_2:: value <--> k_2,k_1::value

3 个答案:

答案 0 :(得分:3)

这类事情的一般技巧是找到规范化 - 一种将特定类的所有成员映射到同一对象的函数。在这种情况下,您可以通过对前两个组件进行排序来实现它,这两个组件将B :: A :: Score转换为A :: B :: Score,同时保持A :: B :: Score不变。

答案 1 :(得分:2)

在我看来,你可以使用这些分数来建立最佳或最差匹配的列表:

d = {
     'id1':  [id_best_match_to_id1, id_next_best_match_to_id1, ..., id_worst_match_to_id1],
     'id2':  [id_best_match_to_id2, id_next_best_match_to_id2, ..., id_worst_match_to_id2],
     ...
}

如果需要保留相似性分数,请使用(id_best_match_to_id1, similarity_score_to_id1)形式的元组列表。

我没有看到利用这种相似性的方法是sim(x,y)==sim(y,x)的对称关系。

答案 2 :(得分:0)

数据看起来非常像加权图的节点和边。如果ab类似,得分为5.0,类似于c且得分为1.0,那么您可能会将其显示为:

                                    a
                                   / \
                                  /   \
                                5.0   1.0
                                /       \
                               b         c

Networkx是一个python库,提供现成的图形对象和算法。将数据加载到加权多图中(即,它支持节点A--BB--A之间的多个连接是微不足道的。之后,在给定对象id的情况下获取最相似的对象是查找节点,找到它的最大加权边缘并在其末尾返回节点。

import networkx as nx

## Test data
data = """\
a::b::2
b::a::3
a::c::5
b::e::1
"""
rows = (row.split('::') for row in data.split())


class Similarity(object):
    def __init__(self, data):
        self.g = nx.MultiGraph()
        self.load(data)

    def load(self, data):
        ## Turn the row into data suitable for networkx graph
        rows = ((row[0], row[1], float(row[2])) for row in data)
        self.g.add_weighted_edges_from(rows)

    def most_similar(self, obj_id):
        ## Get edges from obj_id node
        edges = self.g.edges_iter(obj_id, data=True)
        ## Sort by weight, get first, get joined node
        return sorted([(i[0], i[1], i[2].get('weight', 0)) for i in edges])[-1][1]


sc = Similarity(rows)
sc.most_similar('a') ## 'c'
## Add some more data linking a --> f with a high score
sc.load([('a', 'f', 10)])
sc.most_similar('a') ## 'f'