如何创建一个元组,其中每个成员都通过表达式进行比较?

lui*_*eca 8 ruby python haskell

嗯,这是事情:

我有以下Haskell代码,这个:

[ (a, b, c) | c <- [1..10], b <- [1..10], a <- [1..10], a ^ 2 + b ^ 2 == c ^ 2 ]
Run Code Online (Sandbox Code Playgroud)

哪个会回来

[(4,3,5),(3,4,5),(8,6,10),(6,8,10)]
Run Code Online (Sandbox Code Playgroud)

对于那些不熟悉这个的人,我会解释:

  • 它返回一个tuple(a,b,c),其中这些"定义"(a,b,c)中的每一个都接收一个列表(1到10),并且他的成员通过a ^ 2 + b ^ 2 == c ^ 2 ?表达式(每个成员)进行比较.

我怎样才能在Python/Ruby中做同样的事情(如果可能的话,一行)?

PS: 它们按字典顺序进行比较.

Luk*_*ard 12

在Python中有一条长行并且没有导入.Python的列表推导可以与多个变量一起使用:

>>> [ (a, b, c) for c in range(1, 11) for b in range(1, 11) for a in range(1, 11) if a*a + b*b == c*c ]
[(4, 3, 5), (3, 4, 5), (8, 6, 10), (6, 8, 10)]


Vic*_*gin 11

Ruby解决方案:

(1..10).to_a.repeated_permutation(3).select { |a, b, c| a*a + b*b == c*c }
# => [[3, 4, 5], [4, 3, 5], [6, 8, 10], [8, 6, 10]] 
Run Code Online (Sandbox Code Playgroud)


zee*_*kay 9

Python解决方案,使用itertools.product,相当于生成器表达式中的嵌套for循环:

[(a,b,c) for c,b,a in product(range(1,11), repeat=3) if a*a + b*b == c*c]
Run Code Online (Sandbox Code Playgroud)

  • `product(range(1,11),repeat = 3)` (4认同)

tok*_*and 5

Ruby替代方案,不强制使用相同的范围:

>> (1..10).to_a.product((1..10).to_a, (1..10).to_a).select { |a, b, c| a*a + b*b == c*c }
#=> [[3, 4, 5], [4, 3, 5], [6, 8, 10], [8, 6, 10]]
Run Code Online (Sandbox Code Playgroud)

你可以说这不会返回预期的结果,那是因为你使用c-> b-> a迭代但返回(a,b,c).所以我担心在Ruby中,没有列表推导,我们需要做这样的事情(map_select = map + compact):

>> (1..10).to_a.product((1..10).to_a, (1..10).to_a).map { |c, b, a| [a, b, c] if a*a + b*b == c*c }.compact
 #=> [[4, 3, 5], [3, 4, 5], [8, 6, 10], [6, 8, 10]]
Run Code Online (Sandbox Code Playgroud)

不是vanilla Ruby,但是使用酷库lazylist你可以写:

>> list { [a, b, c] }.where(:c => (1..10), :b => (1..10), :a => (1..10)) { a*a + b*b == c*c }.to_a
#=> [[4, 3, 5], [3, 4, 5], [8, 6, 10], [6, 8, 10]]
Run Code Online (Sandbox Code Playgroud)