【问题标题】:Python, most efficient structure for an n key lookupPython,用于 n 键查找的最有效结构
【发布时间】:2017-11-28 16:16:50
【问题描述】:

我有一组数据需要根据键来查找:

#  fk is a comparsion function
#  Keys go from 1 to n
#  Assume that this is done whilst going through rows that have said keys and item inside

if f1(key1, val1) and f2(key2, val2)... and fn(keyn, valn):
    return item

在 python 中进行这种查找最有效的数据结构和算法集合是什么。最好存在于默认库或维护良好的库中。目前我正在寻找类似于 boost 的多地图的东西,但我认为可能有更好的方法。

在我的情况下,我正好有 3 个键,比较函数是 '' 和 '==' 但我问的是一般情况,因为我认为可能会弹出类似的问题(或者可能有之前弹出,我找不到它们。

【问题讨论】:

  • 我在这里没有看到任何比较 - 只有键/值对...
  • 你的函数可以在列表中吗?您的密钥可以在列表中吗?
  • @khelwood 是的,是的,我不明白为什么不
  • @alfasin 我写的是一个通用案例,假设 fk 是一个函数,如果给定一个键和一个值,则返回一个布尔值
  • @George 如果我不得不问这个问题,我会问“我有一组来自 1...n 的键和一组来自 1...n 的值如何比较相同的键 或 == 值的索引”我只是说围绕这个问题转来转去会浪费每个人的时间。也不清楚 fk 是否是一个比较函数,为什么会有不同的 f

标签: python algorithm python-3.x search data-structures


【解决方案1】:

假设你有函数列表和对应的参数

functions = [f1, f2, f3]
keyvalues = [(key1, val1), (key2, val2), (key3, val3)]

您可以将两者压缩在一起,并使用生成器表达式将函数应用于参数,生成器表达式将成为all 函数的参数:

if all(f(*args) for (f, args) in zip(functions, keyvalues)):

【讨论】:

  • 是的,但是如果我的值列表变得更大,这将是非常低效的 [总是 O(n) 昂贵的操作]。 Henece 为什么我要一个可以优化这个的库(例如,它根据 f 的类型生成数据结构来排列数据,以便可以在 O(1) 时间内完成的任何搜索,例如寻找key==value 在 O(1) 时间内处理,留下较小的数据结构,必须使用 O(logn) 函数完成查找......留下查找函数为 O(n)) 的数据结构跨度>
  • 您使用的是 Python 3; zip 返回一个按需生成元素的迭代器。此外,all 短路:如果第一个函数的计算结果为False,它会立即返回False,而不消耗zip 返回的其余迭代器。
  • 如果您使用的是 Python 2,您需要做的唯一更改就是将 zip 替换为 itertools.izip。
  • 您可能想展示一个您实际使用的函数类型的具体示例。你一直说你有 3 个函数,并暗示你也有 3 组值可以应用它们。现在你有 3+-百万的价值?将您的基准代码添加到问题中,我们可能会更好地了解您想要什么。
  • 您可以通过显示使该解决方案站不住脚的基准来使其更加清晰。
【解决方案2】:
from functools import partial

from operator import lt, le, eq, ne, ge, gt
from pprint import pprint as pp

def data_extract(funcs, keys, table):
    assert len(funcs) == len(keys) == len(table[0]), \
           'Error: incompatable data sizes'
    # substitutes for *first* param
    pfuncs = [partial(f, k) for f, k in zip(funcs, keys)] 
    return [row for row in table 
            if all(p(value) 
                   for p, value in zip(pfuncs, row))]

def skip(a, b):
    return True

tbl = [[1, 2, 3],
       [2, 3, 4],
       [4, 6, 8],
       [10, 12, 14],
       # ... millions
       ]

fn = [ge, le, skip]
ks = [12, 6, None]

ans = data_extract(fn, ks, tbl)
pp(ans)  # [[4, 6, 8], [10, 12, 14]]

希望以上是对您问题的正确解释。如果每次调用函数时 funcs 和/或 keys 都会发生变化,我无法弄清楚如何使用 dict 来提供帮助。

skip 只是说明表中该列中的数据是“无关紧要”的一种方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 2013-04-13
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多