2

タプルのリストとして表される階層的なキーワードツリーがあります。最初の引数は「パス」で、2番目の引数は対応するキーワードです。

keys = [('0','key1'),('0,1','key2'),('0,1,12','key3'),('0,2','key4'),('0,2,30','key5')]

「パス」と対応するドキュメントを接続するリスト(1つのドキュメントに複数の「パス」を含めることができます):

docs = [('0,1,12','doc1'),('0,2,30','doc1'),('0,1','doc2')]

各ドキュメントをキーワードに一致させて、次のような結果を生成したいと思います。

docdict={doc1:[('key1','key2','key3'),('key1','key4','key5')],doc2:[('key1','key2')]}

私の質問は、すべての(親)キーワードを最も効果的に取得する方法ですか?前もって感謝します!

4

4 に答える 4

1

あなたがこれらをたくさん持っているならば、おそらくより良くスケーリングするであろうより読みやすい答え。

docs = [('0,1,12','doc1'),('0,2,30','doc1'),('0,1','doc2')]
keys = [('0','key1'),('0,1','key2'),('0,1,12','key3'),('0,2','key4'),('0,2,30','key5')]

keydict = dict(keys)
resultDict = {}

for doc in docs:
    (path, docname) = doc
    pathList = path.split(',')
    keyPath = []
    for i in range(0, len(pathList)):
        aPath = ','.join(pathList[:i+1])
        keyPath.append(keydict[aPath])

    if docname not in resultDict :
        resultDict[docname] = []
    resultDict[docname].append(tuple(keyPath))

print resultDict  
于 2012-05-16T10:47:41.020 に答える
1

これも別の解決策です。

keys = [('0','key1'),('0,1','key2'),('0,1,12','key3'),('0,2','key4'),('0,2,30','key5')]
docs = [('0,1,12','doc1'),('0,2,30','doc1'),('0,1','doc2')]

def get_path(p):
    # tuples so that you can use them as dict keys
    return tuple(p.split(','))

# we need to find the keys based on the paths, so make the path the dict's key
keypaths = {get_path(p): key for p, key in keys}

docdict = {}
for p, doc in docs:
    path = get_path(p) # we need the path as a tuple or list, so that you can get the parents via slicing
    # get all parents of the path and the path itself.
    # we remove one part of the path at a time and keep the original path also
    all_paths = [path]+[path[:-i] for i in range(1,len(path))]
    # you need to keep each doc/path combination alone, so you need a list to store it
    if doc not in docdict:
        docdict[doc] = []
    # add the keys whose path is in one of the parents or the path itself
    docdict[doc].append([keypaths[path] for path in all_paths if path in keypaths])

print docdict # now, you see what you expect. :)

率直に言って、これらすべてのワンライナーでは、コードが読めなくなります。したがって、同意する場合は、このソリューションを気に入っていただけるはずです。

于 2012-05-16T10:53:54.203 に答える
1

これはほとんどあなたが望むことをします:

>>> docdict = {doc[-1]:[key[-1] for key in keys if doc[0].startswith(key[0])] for doc in docs}
>>> docdict
{'doc2': ['key1', 'key2'], 'doc1': ['key1', 'key4', 'key5']}

そして、これはあなたが指定したことを正確に行います:

>>> docdict = {}
>>> for doc in docs:
    docdict.setdefault(doc[-1],[]).append(tuple(key[-1] for key in keys if doc[0].startswith(key[0])))  
>>> docdict
{'doc2': [('key1', 'key2')], 'doc1': [('key1', 'key2', 'key3'), ('key1', 'key4', 'key5')]}

両方ありO(n*m)ます。

于 2012-05-16T10:37:38.180 に答える
0

編集:最初にキーワードから直接の親を取得するメソッドを作成しましたが、それは要件に答えません。私が理解したことから、パスからすべての親キーワードを取得する方がはるかに優れています。

>>> def get_parents(keys, path):
    """ Get all parent keywords """
    # Get parent path (remove after last ',')
    parent_paths = [path]
    while ',' in path:
        path = ','.join(path.split(',')[:-1])
        parent_paths.append(path)
    return [key for path, key in keys if path in parent_paths]

>>> get_parents(keys, '0,2')
['key1', 'key4']
>>> from collections import defaultdict
>>> def create_doc_dict(keys, docs):
    """ Create the required dict """
    docdict = defaultdict(list)
    for path, doc in docs:
        docdict[doc].append(get_parents(keys, path))
    return docdict

>>> create_doc_dict(keys, docs)
defaultdict(<type 'list'>, {'doc2': [['key1', 'key2']], 'doc1': [['key1', 'key2', 'key3'], ['key1', 'key4', 'key5']]})
于 2012-05-16T10:37:21.627 に答える