2

给定一个表达式:

(A OR B) AND (C OR D) AND (X OR Y OR Z)

我需要分发和生成组合ACX, ACY, ACZ, ADX, ADY, ADZ, BCX, BCY, BCZ, BDX,BDYBDZ. 我们有一个用户界面,用户可以使用它来生成上述表达式。在后端,我们需要生成不同的组合,以便更轻松地与 ACX、ACY 等一组元素进行匹配。

具有 AND 的组的数量不是固定的,每个 AND 组中的元素的大小也不同。

关于如何完成这项工作有什么想法?我正在尝试用递归编写它,并查看其他人是否有更聪明的答案或者是否存在库。

4

4 回答 4

6

尝试:

AB = %w[A B]
CD = %w[C D]
XYZ = %w[X Y Z]

AB.product(CD, XYZ).join(&:map)

它返回一个数组,如:

[
  "ACX",
  "ACY",
  "ACZ",
  "ADX",
  "ADY",
  "ADZ",
  "BCX",
  "BCY",
  "BCZ",
  "BDX",
  "BDY",
  "BDZ"
]

Ruby 的Array.product文档说:

------------------------------------------------------------------------------
  ary.product(other_ary, ...)                -> new_ary
  ary.product(other_ary, ...) { |p| block }  -> ary


------------------------------------------------------------------------------

Returns an array of all combinations of elements from all arrays. The length of
the returned array is the product of the length of self and the argument
arrays. If given a block, product will yield all combinations and
return self instead.

  [1,2,3].product([4,5])     #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
  [1,2].product([1,2])       #=> [[1,1],[1,2],[2,1],[2,2]]
  [1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
                             #    [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
  [1,2].product()            #=> [[1],[2]]
  [1,2].product([])          #=> []

您的问题特别感兴趣的是第三个示例。

于 2013-06-17T18:44:48.900 回答
1

这不是完整的方法,但我会慢慢使用Array#product. 给我一点时间。

a1 = ['A','B']
a2 = ['C','D'] 
a3 = ['X','Y','Z']

a1.product(a2).product(a3)
# => [[["A", "C"], "X"],
#     [["A", "C"], "Y"],
#     [["A", "C"], "Z"],
#     [["A", "D"], "X"],
#     [["A", "D"], "Y"],
#     [["A", "D"], "Z"],
#     [["B", "C"], "X"],
#     [["B", "C"], "Y"],
#     [["B", "C"], "Z"],
#     [["B", "D"], "X"],
#     [["B", "D"], "Y"],
#     [["B", "D"], "Z"]]

这是完整的解决方案(我用作Array数据结构来保留您所要求的所有结果组合):

a1.product(a2).map(&:join).product(a3).map(&:join)
# => ["ACX",
#     "ACY",
#     "ACZ",
#     "ADX",
#     "ADY",
#     "ADZ",
#     "BCX",
#     "BCY",
#     "BCZ",
#     "BDX",
#     "BDY",
#     "BDZ"]

更简单的方法是:

a1.product(a2,a3).map(&:join)
# => ["ACX",
#     "ACY",
#     "ACZ",
#     "ADX",
#     "ADY",
#     "ADZ",
#     "BCX",
#     "BCY",
#     "BCZ",
#     "BDX",
#     "BDY",
#     "BDZ"]
于 2013-06-17T18:28:34.527 回答
0

在一般情况下,您可以使用递归下降解析器处理此问题:

def expression(stream)
  ret = primary(stream);
  while stream.length > 0 && stream[0] != ")"
    token = stream.shift
    if token == "AND"
      ret = ret.product(primary(stream)).map(&:join)
    elsif token == "OR"
      ret += primary(stream);
    elsif token == "("
      raise "unexpected ("
    end
  end
  return ret
end

def primary(stream) 
  if stream[0] == "("
    stream.shift
    ret = expression(stream)
    raise ") expected" unless stream.shift == ")"
  elsif stream[0] == ")"
    raise "unexpected )"
  else
    ret = [ stream.shift ];
  end
  return ret
end

def parse(str)
  return expression(str.scan(/\)|\(|\w+/))
end

parse('(A OR B) AND (C OR D) AND (X OR Y OR Z)')

=> ["ACX", "ACY", "ACZ", "ADX", "ADY", "ADZ", 
    "BCX", "BCY", "BCZ", "BDX", "BDY", "BDZ"]
于 2013-06-17T18:50:00.803 回答
-3

如果你的意思是ANDOR作为逻辑连接词andor,那么这是不可能的。该表达式(A OR B) AND (C OR D) AND (X OR Y OR Z)具有某个单一的值。你无法进​​入其中。

于 2013-06-17T18:35:35.637 回答