给出一个表达式:
(A OR B) AND (C OR D) AND (X OR Y OR Z)
我需要分发和生成组合ACX
,ACY
,ACZ
,ADX
,ADY
,ADZ
,{{1} },BCX
,BCY
,BCZ
,BDX
和BDY
。我们有一个用户用来生成上述表达式的UI。在后端,我们需要生成不同的组合,以便更容易地匹配一组元素,如ACX,ACY等。
具有AND的组的数量不固定,每个AND组中的元素的大小也不同。
关于如何完成这项工作的想法是什么?我试图用递归编写它,并试图看看其他人是否有更聪明的答案或是否存在库。
答案 0 :(得分: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([]) #=> []
您的问题特别感兴趣的是第三个例子。
答案 1 :(得分:2)
这不是完整的方法,但我将使用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"]
答案 2 :(得分: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"]
答案 3 :(得分:-3)
如果您的意思是AND
和OR
作为逻辑连接词and
和or
,那么这是不可能的。
表达式(A OR B) AND (C OR D) AND (X OR Y OR Z)
具有特定的单个值。你无法进入它。