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块是如何工作的。
答案 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
的人,因此是第二个值。 c
和d
都评估为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