2
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 块是如何工作的。

4

3 回答 3

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是第一个满足 as 的trued是唯一评估为 的值false

希望有帮助。

于 2011-10-14T15:27:52.597 回答
0

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

因此,例如,第一个表示询问每个元素是否为“a”。第一个说是,所以“a”被认为是唯一的。第二个说不,所以“b”被认为是唯一的。其他人也说不,所以它们不被认为是唯一的(因为“不”的响应是我们已经看到的)。

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

于 2011-10-14T15:24:13.013 回答
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
于 2011-10-14T16:10:26.487 回答