【问题标题】:How do I implement a dictionary "with a Python tuple" as key in C++?如何实现字典“带有 Python 元组”作为 C++ 中的键?
【发布时间】:2010-06-16 14:04:37
【问题描述】:

我目前有一些我想移植到 C++ 的 python 代码,因为它目前比我希望的要慢。问题是我在其中使用了一个字典,其中键是一个由一个对象和一个字符串组成的元组(例如(obj,“word”))。 我到底如何在 C++ 中编写类似的东西?也许我的算法太可怕了,有什么方法可以在不求助于 C++ 的情况下让它更快?

为清楚起见,下面的整个算法。字典“post_score”是问题所在。

def get_best_match_best(search_text, posts):
    """
    Find the best matches between a search query "search_text" and any of the
    strings in "posts".

    @param search_text: Query to find an appropriate match with in posts.
    @type search_text: string
    @param posts: List of candidates to match with target text.
    @type posts: [cl_post.Post]
    @return: Best matches of the candidates found in posts. The posts are ordered
    according to their rank. First post in list has best match and so on.
    @returntype: [cl_post.Post]
    """
    from math import log

    search_words = separate_words(search_text)
    total_number_of_hits = {}
    post_score = {}
    post_size = {}
    for search_word in search_words:
        total_number_of_hits[search_word] = 0.0
        for post in posts:
            post_score[(post, search_word)] = 0.0
            post_words = separate_words(post.text)
            post_size[post] = len(post_words)
            for post_word in post_words:
                possible_match = abs(len(post_word) - len(search_word)) <= 2
                if possible_match:
                    score = calculate_score(search_word, post_word)
                    post_score[(post, search_word)] += score
                    if score >= 1.0:
                        total_number_of_hits[search_word] += 1.0

    log_of_number_of_posts = log(len(posts))
    matches = []
    for post in posts:
       rank = 0.0
       for search_word in search_words:
           rank += post_score[(post, search_word)] * \
                  (log_of_number_of_posts - log(1.0 + total_number_of_hits[search_word]))
       matches.append((rank / post_size[post], post))
    matches.sort(reverse=True)
    return [post[1] for post in matches]

【问题讨论】:

  • 说真的,如果代码已经没有错误,为什么不利用现有的工具呢?你看,Joe Polski 不建议重写。
  • @Hamish Grubijan:Joe Polski 是谁,我为什么要关心他的建议?
  • @sbk 你应该关心,因为他的话就是法律。
  • @Ignacio Vazquez-Abrams:不,但我会调查一下。谢谢。 :) @Hamish Grubijan:“利用现有工具”是什么意思?
  • @MdaG,我的意思是Cython,还有其他我听说过但忘记名字的工具。

标签: c++ python dictionary


【解决方案1】:

map&lt;pair&lt;..., string&gt;, ...&gt; 如果你一心想要使用 C++ 来做这件事。

【讨论】:

  • 如果 MdaG 真的很顽固,我想他会使用大写锁定。
  • 谢谢,pair 是我所缺少的。 :-) 如果我可以使用 Cython 或更好的算法,那我也不死心。 :-)
【解决方案2】:

这一次,您为search_words 中的每个search_word 调用了separate_words(post.text)。对于posts 中的每个post,您应该只调用一次separate_words。

即,而不是:

for search_word in search_words:
    for post in posts:
        # do heavy work

你应该有:

for post in posts:
    # do the heavy works
    for search_word in search_words:
        ...

如果我怀疑,separate_words 做了很多字符串操作,不要忘记字符串操作在 python 中相对昂贵,因为字符串是不可变的。

您可以做的另一项改进是,您不必将 search_words 中的每个单词与 post_words 中的每个单词进行比较。如果您保持 search_words 和 post_words 数组按字长排序,那么您可以使用滑动窗口技术。基本上,由于 search_word 只会匹配一个 post_word 如果它们的长度差异小于 2,那么您只需在两个长度差异的窗口中进行检查,从而减少要检查的单词数量,例如:

search_words = sorted(search_words, key=len)
g_post_words = collections.defaultdict(list) # this can probably use list of list
for post_word in post_words:
    g_post_words[len(post_word)].append(post_word)

for search_word in search_words:
    l = len(search_word)
    # candidates = itertools.chain.from_iterable(g_post_words.get(m, []) for m in range(l - 2, l + 3))
    candidates = itertools.chain(g_post_words.get(l - 2, []), 
                                 g_post_words.get(l - 1, []), 
                                 g_post_words.get(l    , []),
                                 g_post_words.get(l + 1, []),
                                 g_post_words.get(l + 2, [])
                                )
    for post_word in candidates:
        score = calculate_score(search_word, post_word)
        # ... and the rest ...

(此代码可能无法按原样运行,只是为了说明这个想法)

【讨论】:

  • 这是有价值的输入,您是正确的。我不熟悉 itertools,但这是阅读它的好时机。谢谢你。 :)
猜你喜欢
  • 1970-01-01
  • 2019-02-12
  • 2010-10-31
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 2021-09-21
相关资源
最近更新 更多