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

发布于 2024-12-10 02:06:01 字数 348 浏览 5 评论 0原文

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

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"]

I understand the regular expression, I don't understand how does the uniq block work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏天碎花小短裙 2024-12-17 02:06:01

这有点棘手。

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 的值。

希望有帮助。

That's a bit of a tricky one.

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

The x in this block is every value in the array. You define uniqueness by "does the string start with a?". Value a is the first to evaluate as true and is therefore the first value. b is the first to evaluate as false so is the second value. Both c and d also evaluate as false, but are not unique since a value that evaluated false was already found.

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

The same holds here. a is the first (false) and b the second (true).

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

Here you see that a is the first false value and c the first value to evaluate as true and therefore the second unique value.

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

Here you have defined uniqueness by "does the string match an array of regular expressions that do match strings not starting with c". Weird!

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

Here you have defined a character class. You defined uniqueness by "strings containing a, b or c". a is the first to satisfy as true. d is the only value to evaluate as false.

Hope that helps.

如此安好 2024-12-17 02:06:01

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

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

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

The determination of uniqueness is based on the result from passing each element to the block.

So, for example, the first one represents asking each element whether they are "a". The first one says yes, so "a" is considered unique. The second one says no, so "b" is considered unique. The others also say no, so they are not considered unique (since the response "no" is one we've already seen).

However, what I can't explain easily is why this appears to be working for you in Ruby 1.8.7; in 1.8.7 and prior a block argument to Array#uniq was ignored. This feature was added in Ruby 1.9. Perhaps you have a patched version?

独闯女儿国 2024-12-17 02:06:01

这样看:当您将 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

Look at this way: when you use uniq with a block, you effectively build an array of arrays where each inner array is [result_of_block, array_element] and then look for unique values in the first elements. So, if we start with:

c = %w(a b c d)

and look at

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

then the array of arrays would look this:

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

Looking for unique values amongst the first elements yields 'a' and nil:

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

and unwrapping yields ['a', 'b']. There's no guarantee that you'll get 'b' as the second element though.

You can write your own uniq_by like this:

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

or this:

def uniq_by(a, &block)
    h = { }
    a.each { |x| h[block.call(x)] = x ] }
    h.values
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文