【问题标题】:Find all "and" combinations from multiple sets从多个集合中查找所有“和”组合
【发布时间】:2015-11-06 17:35:06
【问题描述】:

假设我有x 对象集,每个集合都有一定数量的对象。我想创建一个数组来存储这些对象的所有唯一“和”组合。

例如,如果我在集合 A 中有 5 个对象,在集合 B 中有 10 个对象,在集合 C 中有 8 个对象,那么我知道从每个集合中挑选一个对象有 5*10*8 = 400 种不同的方式.但我想将这些组合实际存储在一个数组中。

所以数组将是多维的,类似于:

{
  { a, a, a }
  { a, a, b }
  { a, a, c }
  ...
  { a, b, a }
  { a, b, b }
  and so on...
}

我需要尽可能高效的解决方案,因为我正在处理可能存在数千万种组合的情况。我不完全确定如何开始解决这个问题。

抱歉,如果不清楚,但我真的不知道该怎么称呼我想要实现的目标,所以我只是尽我所能描述它。感谢您提供的任何帮助。

编辑:以下是有关该问题的更多信息:

这个问题的目的是我要从每个结果数组中计算一个“分数”值。然后,我想找到最高的n 分数并将它们返回给用户。所以实际上,我相信我不需要将整个数组放在内存中。我可以遍历数组,计算分数,如果分数足够高,则将其添加到返回的数组中。那样的话,我只需要内存中连续的顶部n对象。

我希望这能让事情更清楚。

【问题讨论】:

  • 几个 cmets:从符号上讲,我认为 set 不能多次拥有相同的元素。或者,至少要知道,当您使用它们的set() 时,某些语言(例如 Python)会重复数据删除。其次 - 拥有数以千万计的连击,您是否一次需要整个阵列?或者你可以迭代每一个。否则你可能会遇到内存大小问题,不是吗?
  • 嘿,如果不清楚,抱歉。每个集合 A、B、C 中的对象都是唯一的。如果您指的是符号{ a, a, a },我想说的是{ object a from set a, object a from set b, object a from set c } 等...
  • 啊,明白了,然后忽略第一点。第二个仍然存在。
  • 是的,我只是要遍历数组中的每个对象,所以我不需要一次全部。那我是不是要把它写到磁盘什么的,然后一块一块地读取呢?
  • 如果您一次不需要所有项目,那么您不需要创建整个阵列,也不需要从磁盘或任何东西写入/读取它。如果ABC 各有 1000 个元素,那就是 10 亿个组合,但您的程序只需要在给定时间存储这 3*1000 个元素。

标签: arrays combinations


【解决方案1】:

快速python,可能无法提高效率,因为您需要在某些时候进行迭代......

getItems(A, B, C):
    for a in A:
        for b in B:
            for c in C:
                items = (a, b, c) ## or [a, b, c], as desired
                yield items

或者,如果您熟悉生成器表达式:

gen = ((a, b, c) for a in A for b in B for c in C)

然后使用:

for combo in getItems(A, B, C): ## or for combo in gen:
    ## do stuff here

编辑:

def getItems(*allSets):
    if len(allSets) == 0:
        yield []
        return
    thisSet, theRest = allSets[0], allSets[1:]
    for value in thisSet:
        for values in getItems(*theRest):
            yield [value] + values

【讨论】:

  • 您好,谢谢您的回复!我对此很熟悉。但是,有没有办法递归地做到这一点?我不一定知道有多少套。
  • 最后一点还不行;无法连接列表 [value] 和生成器 getItems(theRest),但我正在处理它
【解决方案2】:

您知道设计时的集合数吗?如果是这样,我会做嵌套的 for 循环。如果您不知道集合的数量,那么您可能会执行某种形式的递归来处理循环。

话虽如此,我认为根据定义,您正在做的事情并不高效。您是否有理由需要将所有可能的组合存储在内存中,而不是根据需要即时生成它们?

【讨论】:

  • 对于递归,您需要一个集合对象数组(java 中的数组数组,依此类推)。您的递归将遍历该主数组,传递要循环遍历的集合的索引,以及它之前的当前选定元素。
  • 请看编辑,希望它能让问题更清楚。
  • @Charles 这说明了一点。在您的情况下,我绝对不会将所有内容存储在 RAM 中。只有前 n 个分数,以及他们的分数,所以您可以在更高的分数出现时替换值。我也可能会使用链表或平衡树,所以一旦找到 n 个项目,您就可以保持分数顺序并删除最低分数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多