解释Ruby Array uniq方法的一个表达式

时间:2011-10-14 15:07:31

标签: ruby arrays uniq

c = %w(a b c d)
1.8.7 :025 > c.uniq {|x|x[/^a/]}
=> ["a", "b"] 
1.8.7 :026 > c.uniq {|x|x[/^b/]}
=> ["a", "b"] 
1.8.7 :027 > c.uniq {|x|x[/^c/]}
=> ["a", "c"] 
1.8.7 :029 > c.uniq {|x|x =~ [/^c/]}
=> ["a"] 
1.8.7 :030 > c.uniq {|s|s[/[^abc]/]}
=> ["a", "d"]

我理解正则表达式,我不明白uniq块是如何工作的。

3 个答案:

答案 0 :(得分:4)

这有点棘手。

c = %w(a b c d)
1.8.7 :025 > c.uniq {|x|x[/^a/]}
=> ["a", "b"] 

此块中的x是数组中的每个值。您可以通过“字符串以a开头吗?”来定义唯一性。值a是第一个评估为true的值,因此是第一个值。 b是第一个评估为false的人,因此是第二个值。 cd都评估为false,但由于已经找到了评估false的值,因此不是唯一的。

1.8.7 :026 > c.uniq {|x|x[/^b/]}
=> ["a", "b"] 

这同样适用。 a是第一个(false)和b第二个(true)。

1.8.7 :027 > c.uniq {|x|x[/^c/]}
=> ["a", "c"] 

您在此处看到a是第一个false值,c是第一个评估为true的值,因此是第二个唯一值。

1.8.7 :029 > c.uniq {|x|x =~ [/^c/]}
=> ["a"] 

在这里,您已经定义了唯一性“字符串是否匹配正则表达式数组,这些正则表达式匹配不以c开头的字符串”。怪异!

1.8.7 :030 > c.uniq {|s|s[/[^abc]/]}
=> ["a", "d"]

在这里您定义了一个角色类。您通过“包含a,b或c的字符串”定义了唯一性。 a是第一个满足true的人。 d是评估为false的唯一值。

希望有所帮助。

答案 1 :(得分:0)

唯一性的确定基于将每个元素传递给块的结果。

因此,例如,第一个代表询问每个元素是否为“a”。第一个说是,所以“a”被认为是独一无二的。第二个说不,所以“b”被认为是独一无二的。其他人也说不,所以他们不被认为是独特的(因为回答“不”是我们已经看过的)。

然而,我无法轻易解释的原因是为什么在Ruby 1.8.7中这似乎对你有用;在1.8.7和之前,Array#uniq的块参数被忽略。 Ruby 1.9中添加了此功能。也许你有一个补丁版本?

答案 2 :(得分:0)

以这种方式看待:当您对块使用uniq时,您可以有效地构建一个数组数组,其中每个内部数组都是[result_of_block, array_element],然后在第一个元素中查找唯一值。所以,如果我们开始:

c = %w(a b c d)

并查看

c.uniq {|x|x[/^a/]}

然后数组数组看起来像这样:

[
    ['a', 'a'],
    [nil, 'b'],
    [nil, 'c'],
    [nil, 'd']
]

在第一个元素中查找唯一值会产生'a'nil

[
    ['a', 'a'],
    [nil, 'b']
]

并展开收益率['a', 'b']。我不能保证你会将'b'作为第二个元素。

您可以像这样编写自己的uniq_by

def uniq_by(a, &block)
    Hash[a.map { |x| [ block.call(x), x] }].values
end

或者这个:

def uniq_by(a, &block)
    h = { }
    a.each { |x| h[block.call(x)] = x ] }
    h.values
end