Ruby 如何在表达式中分布元素?
给出一个表达式:Ruby 如何在表达式中分布元素?,ruby,algorithm,distribution,Ruby,Algorithm,Distribution,给出一个表达式: (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。我们有一个用户界面,用户使用它来生成上述表达式。在后端,我们需要生成不同的组合,以便更容易地匹配一组元素,如ACX、ACY等 具有and的组的数量不是固定的,每个and组中的元素大小也不同 你对如何完成这项工作有什么想法?我试图用递归来编写它,看看其他人是否有更聪明的答案,或者是否存
(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
。我们有一个用户界面,用户使用它来生成上述表达式。在后端,我们需要生成不同的组合,以便更容易地匹配一组元素,如ACX、ACY等
具有and的组的数量不是固定的,每个and组中的元素大小也不同
你对如何完成这项工作有什么想法?我试图用递归来编写它,看看其他人是否有更聪明的答案,或者是否存在库。这不是完整的方法,但我将使用递归慢慢地实现这一点。给我点时间
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"]]
以下是完整的解决方案(我使用数组
作为数据结构,以按照您的要求保留所有结果组合):
更简单的方法是:
a1.product(a2,a3).map(&:join)
# => ["ACX",
# "ACY",
# "ACZ",
# "ADX",
# "ADY",
# "ADZ",
# "BCX",
# "BCY",
# "BCZ",
# "BDX",
# "BDY",
# "BDZ"]
这并不是完整的方法,但我将使用。给我点时间
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"]]
以下是完整的解决方案(我使用数组
作为数据结构,以按照您的要求保留所有结果组合):
更简单的方法是:
a1.product(a2,a3).map(&:join)
# => ["ACX",
# "ACY",
# "ACZ",
# "ADX",
# "ADY",
# "ADZ",
# "BCX",
# "BCY",
# "BCZ",
# "BDX",
# "BDY",
# "BDZ"]
如果你是说
和和或作为逻辑连接词和和或,那么这是不可能的。
表达式(A或B)和(C或D)以及(X或Y或Z)
具有特定的单个值。你不能进入它。如果你指的是和和或作为逻辑连接词和和或,那么这是不可能的。
表达式(A或B)和(C或D)以及(X或Y或Z)
具有特定的单个值。你无法进入它。试试:
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的文档说:
------------------------------------------------------------------------------
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([]) #=> []
您的问题特别感兴趣的是第三个示例。试试:
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的文档说:
------------------------------------------------------------------------------
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([]) #=> []
您的问题特别感兴趣的是第三个示例。您可以使用递归下降解析器在一般情况下处理此问题:
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"]
您可以使用递归下降解析器在一般情况下处理此问题:
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"]
你所说的和和或是什么意思?Ruby没有这样的表达式。你是说逻辑的和和还是?如果你是这个意思,那是不可能的。谢谢@sawa,我不是指任何语言的逻辑连接词——只是一种表示标准的格式。为了完整性接受@the Tin Man下面的答案。有关对解决方案的动态版本感兴趣的人员,请参阅。特别是代码块头,*rest=head.product(*rest)您所说的和以及或的可能重复?Ruby没有这样的表达式。你是说逻辑的和和还是?如果你是这个意思,那是不可能的。谢谢@sawa,我不是指任何语言的逻辑连接词——只是一种表示标准的格式。为了完整性接受@the Tin Man下面的答案。有关对解决方案的动态版本感兴趣的人员,请参阅。特别是代码块头,*rest=head.product(*rest)可能与Thank sawa重复,我不是指任何语言的逻辑连接词,只是表示标准的格式。什么的正式表示?Thank sawa,我不是指任何语言的逻辑连接词——只是一种表示标准的格式。什么的正式表示?非常感谢关于Array.product的提示,我是Ruby新手,所以我不知道。这无疑使解决方案变得优雅。关于您的解决方案,有一个问题-我们如何处理不同数量的阵列。您的示例显示了3个,但如果我们有5个或10个,例如?为了简单起见,我在示例中使用了这一个。您还可以使用-a1.产品(a2、a3、a4等)
a.:)非常感谢关于Array.product的提示,我是Ruby新手,所以我不知道。这无疑使解决方案变得优雅。关于您的解决方案,有一个问题-我们如何处理不同数量的阵列。您的示例显示了3个,但如果我们有5个或10个,例如?为了简单起见,我在示例中使用了这一个。您还可以使用-a1.产品(a2、a3、a4等)
a.:)天啊!您在此处复制了整个文档!!:)我只给了他链接。提供链接是个好主意,这也有助于OP了解其他方法。:)当链接断开时,只提供链接是毫无价值的。我提供了一个链接和相关的部分,这是我们应该做的。这个链接在过去由于各种原因而消失,最终又回来了。它比过去更加稳定,但是,根据大家的共识,我们不应该只使用链接,而应该引用即时内容。我喜欢走路。“AB.product(CD,XYZ).join(&:map)
给出的是“acxacyadzbadzbccybczbdxbdybdz”
。因此,将AB.product(CD,XYZ).join(&:map)
更改为AB.product(CD,XYZ).map(&:join)
。没有调查的人会一直支持你。非常奇怪:)谢谢你指出这一点。当我从IRB复制到我的编辑器formatting.OMG时,这两个被转换了!您在此处复制了整个文档!!:)我只给了他链接。提供链接是个好主意,这也有助于OP了解其他方法。:)当链接断开时,只提供链接是毫无价值的。我提供了一个链接和相关的部分,这是我们应该做的。这个链接在过去由于各种原因而消失,最终又回来了。它比过去更加稳定,但是,根据大家的共识,我们不应该只使用链接,而应该引用即时内容。我喜欢走路。“AB.product(CD,XYZ).join(&:map)
正在给予”ACX