簡體   English   中英

觸發器紅寶石中3點范圍操作符和2點范圍操作符之間的差異

[英]Difference between 3-dot-range operator and 2-dot-range operator in flip flop ruby

請幫助我理解范圍運算符之間的區別.....作為Ruby中使用的“觸發器”。

這是來自Pragmatic Programmers指南的示例:

a = (11..20).collect {|i| (i%4 == 0)..(i%3 == 0) ? i : nil}

返回:

[nil, 12, nil, nil, nil, 16, 17, 18, nil, 20]

也:

a = (11..20).collect {|i| (i%4 == 0)...(i%3 == 0) ? i : nil}

回:

[nil, 12, 13, 14, 15, 16, 17, 18, nil, 20]

觸發器(又名f / f)是源自perl的有狀態運算符。

f / f運算符隱含在ruby中的條件語句(if和ternary)而不是range中,因此(1..5)是一個范圍但是(1..5)? 1:5是af / f。 f / f具有內部狀態(真/假)並且由兩個條件組成。 它在第一個條件評估為真時開啟(狀態變為真),在第二個條件評估為真時關閉。 兩個和三個虛線版本之間的區別在於,雙點在第一個評估為真后立即評估第二個條件,三點不評估。

兩個虛線版本的工作原理如下:

A..B |
A -> false | State -> false
A -> true, B -> false | State -> true # notice how it checks both conditions
B -> false | State -> true
B -> true | State -> false
A -> false  | State -> false
A -> true, B -> true | State -> false

將它與三個虛線版本進行比較

A...B
A -> false | State -> false
A -> true | State -> true # three dotted version doesn't check second condition immediately
B -> false | State -> true
B -> true | State -> false
A -> false | State -> false
A -> true | State -> true

讓我們沿着令人驚嘆的perl文章,但在ruby中有例子

兩個虛線示例:

DATA.each_line do |line|
  print "\t" if (line =~ /^start/ .. line =~ /^end/)
  print line
end

__END__
First line.
start
Indented line
end
Back to left margin

這打印:

First line.
    start
    Indented line
    end
Back to left margin

正如你所看到的那樣 - f / f在第2行打開,在第4行打開。但它有一個微妙之處。 看一下這個:

DATA.each_line do |line|
  print "\t" if (line =~ /start/ .. line =~ /end/)
  print line
end
__END__
First line.
Indent lines between the start and the end markers
Back to left margin

這打印:

First line.
    Indent lines between the start and the end markers
Back to left margin

它在第2行打開並立即關閉。

讓我們假設您不想在第一個操作符之后立即檢查第二個操作符。 這是三點式f / f變得方便的地方。 看看下一個例子。

DATA.each_line do |line|
  print "\t" if (line =~ /start/ ... line =~ /end/)
  print line
end

__END__
First line.
Indent lines between the start and the end markers
So this is indented,
and this is the end of the indented block.
Back to left margin

哪個印刷品:

First line.
    Indent lines between the start and the end markers
    So this is indented,
    and this is the end of the indented block.
Back to left margin

你可以看到它在第2行打開,在第4行打開

現在讓我們將它應用於您的示例

我寫了一個小腳本來說明它的行為

def mod(n, i)
  result = i % n == 0
  puts "#{i} mod #{n} => #{result}"
  result
end

(11..20).each { |i|
  if (mod(4, i))...(mod(3, i)) # NOTE it's a three dotted version
    # NOTE that those puts show previous state, not the current one!
    puts true
  else
    puts false
  end
}

兩個虛線結果:

11 mod 4 => false
false
12 mod 4 => true
12 mod 3 => true # Notice how it checks both conditions here
true
13 mod 4 => false
false
14 mod 4 => false
false
15 mod 4 => false
false
16 mod 4 => true
16 mod 3 => false
true
17 mod 3 => false
true
18 mod 3 => true
true
19 mod 4 => false
false
20 mod 4 => true
20 mod 3 => false
true

三點結果:

11 mod 4 => false
false
12 mod 4 => true
true
13 mod 3 => false
true
14 mod 3 => false
true
15 mod 3 => true # turns OFF here
true
16 mod 4 => true # and turns immediately ON here
true
17 mod 3 => false
true
18 mod 3 => true
true
19 mod 4 => false
false
20 mod 4 => true
true
=> 11..20

PS Range和flip / flop是兩個完全不同的運算符,你不應該混淆它們。

觸發開關的概念實際上來自電子產品 它的主要優點是它記住了它的狀態。 將觸發器布爾范圍視為變量,存儲布爾值。 我們來看看下面的例子:

1.upto(10).each do |i|
  puts i if (i%2==0)..(i%4==0)
end

        #                        vvvv   value of “hidden” state
2       # left range boundary  ⇨ true
3
4       # right range boundary ⇨ false, no 5 follows 
6       # left range boundary  ⇨ true
7
8       # right range boundary ⇨ false, no 9 follows 
10

在你的第一個例子中,“條件”對於4倍數變為true ,在3倍數時變為false 在第二個例子中,條件變量在12上沒有關閉,因為它排除了右邊界( i%3 ),因為它是一個3點范圍。

希望這個例子不是太糾結。

Ruby中2點和3點之間的差異是包含。 例如

(1..100)
=> All numbers starting from 1 and ending at 100 INCLUDING 100

(1...100)
=> All numbers starting from 1 that are less than 100

(1..100).include?(100)
=> true

(1...100).include?(100)
=> false

希望這可以幫助。

當在一個范圍內使用雙點時,它會創建一系列數字,這些數字最多可包含傳入的最大數量。當使用三點時,它會創建一個范圍,該范圍最多但不包括傳入的最大數量。

所以:

 (1..5).each {| i | puts i} #will print 1,2,3,4,5

而:

(1...5).each {| i | puts i} #will print 1,2,3,4

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM