【问题标题】:The optimal data structure for filtering for objects that match criteria筛选符合条件的对象的最佳数据结构
【发布时间】:2019-08-22 05:49:13
【问题描述】:

我会尽量概括地提出问题,任何语言的回复都可以。

假设有几组不同大小,每组都包含与类别有关的任意值:

var colors = ["red", "yellow", "blue"] // 3 items
var letters = ["A", "B", "C", ... ] // 26 items
var digits = [0, 1, 2, 3, 4, ... ] // 10 items
... // each set has fixed amount of items

我已经拥有的这个主列表中的每个对象(我想以某种方式重组以优化搜索)都有属性,每个对象都是这些集合之一的选择,例如:

var masterList = [
  { id: 1, color: "red", letter: "F", digit: 5, ... },
  { id: 2, color: "blue", letter: "Q", digit: 0, ... },
  { id: 3, color: "red", letter: "Z", digit: 3, ... },
  ...
]

搜索的目的是从主列表中创建一个新的可接受对象列表。该程序将根据给定的搜索条件过滤主列表,对于每个属性,这些条件都包含一个可接受值的列表。

var criteria = {
  color: ["red", "yellow"],
  letter: ["A", "F", "P"],
  digit: [1, 3, 5],
  ...
};

我想某种树是最适用的。我的理解是它需要平衡,因此根节点将是“中值”对象。我想每个级别都将由其中一个属性定义,因此当程序从根搜索时,它只会继续符合搜索条件的分支,每次都会消除不适合给定特定属性的对象那个级别。

但是,我了解此主列表中的许多对象将具有匹配的属性值。这以可能有助于快速搜索的图形方式将它们连接起来。

我当前的搜索算法相当直观,只需按原样使用主列表即可。程序

  1. 遍历搜索条件中的属性,
  2. 每个属性都遍历主列表,消除了许多没有匹配属性的对象,并且
  3. 最终删除所有不符合条件的对象。肯定有一些更快的过滤系统涉及到更有条理的数据结构。

我可以从这里去哪里?我对本地数据库开放,而不是我想的另一个数据结构 - GraphQL 看起来很有趣。这是我的第一个 Stack Overflow 问题,所以对于任何不礼貌的行为,我深表歉意????

【问题讨论】:

  • 这里有更新吗?

标签: object search data-structures graph tree


【解决方案1】:

因为我没有关于集合数量的上下文,也没有关于每个集合中元素数量的上下文。我会建议您进行一些非常小的更改,这些更改至少会让您相对较快。

为了保持数学,我将在这里定义几个术语:

  • 组数 - n
  • 主列表大小 - k
  • 搜索条件中每个属性的大小 - p

因此,根据我相信您使用的算法,您正在对搜索条件进行n 迭代,因为搜索条件中可能有n 可能的键。

然后在每个n 迭代中,您都在对该特定集合的允许值进行p 迭代。最后,在每次 np 迭代中,您都在使用 k 迭代对主列表进行迭代,并检查是否应允许该记录值。

因此,在一般情况下,您这样做的时间复杂度为O(npk)

所以,我不建议在这里做太多改动。

您可以做的最好的事情是将搜索条件中的值更改为set(哈希集)而不是将其保留为列表,然后遍历主列表。遵循此 Python 代码:

def is_possible(criteria, master_list_entry): 
    for key, value in master_list_entry.items(): # O(n)
        if not key in criteria or value not in criteria[key]: # O(1) average
            return False
    return True

def search(master_list, criteria):
    ans = []
    for each_entry in master_list: # O(k)
        if is_possible(criteria, each_entry): # O(n), check above
            ans.append(each_entry)
    return ans

只要调用搜索功能,它就会返回过滤后的主列表。

关于更改,请将您的搜索条件更改为:

criteria = {
  color: {"red", "yellow"}, # This is a set, instead of a list
  letter: {"A", "F", "P"},
  digit: {1, 3, 5},
  ...
}

如您所见,我在每一行中都提到了复杂性,因此我们将问题简化为平均情况下的O(nk)

【讨论】:

  • 感谢您的回复!这当然更有效率。如果这是优化的程度,我想我将不得不满足于 O(nk)。然而,令我感到惊讶的是,在执行搜索之前,在主列表的组织方面没有更多可以做的事情。如果这意味着更快的平均搜索时间,我愿意花费大量时间重组原始主列表......即使它仍然是 O(nk)
猜你喜欢
  • 2014-03-21
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 2017-09-26
  • 1970-01-01
  • 1970-01-01
  • 2010-09-05
相关资源
最近更新 更多