มีสิ่งที่ตรงกันข้ามหรือไม่? สำหรับ Ruby Arrays


190

ฉันมีตรรกะดังต่อไปนี้ในรหัสของฉัน:

if !@players.include?(p.name)
  ...
end

@playersเป็นอาร์เรย์ มีวิธีการ!หรือไม่ดังนั้นฉันจึงสามารถหลีกเลี่ยง

โดยหลักแล้วตัวอย่างนี้จะเป็น:

if @players.does_not_include?(p.name)
  ...
end

1
เป็นdoทับทิมถูกต้อง? ฉันได้รับข้อผิดพลาดsyntax error, unexpected end-of-input(ทำงานถ้าฉันลบdo)
maxymoo

ดูstackoverflow.com/a/60404934/128421เพื่อหาเกณฑ์มาตรฐานสำหรับการค้นหาอาร์เรย์กับชุด
ชายดีบุก

คำตอบ:


370
if @players.exclude?(p.name)
    ...
end

ActiveSupport เพิ่มexclude?วิธีการในการArray, และHash Stringนี่ไม่ใช่ทับทิมบริสุทธิ์ แต่ถูกใช้โดยนักทับทิมจำนวนมาก

ที่มา: ส่วนขยายสนับสนุนหลักที่ใช้งานอยู่ (คู่มือราง)



3
หมายเหตุเล็กน้อย: AS เพิ่มลงใน Enumerable เพื่อให้คุณสามารถใช้กับคลาสทั้งหมดซึ่งรวมถึง Enumerable แม้แต่กับแฮช :)
2422869

1
นี่ควรเป็นเครื่องหมายสีเขียว
etlds

วิธีนี้จะไม่โหลดอัตโนมัติใน Rails 4.2.3 (และอาจเป็นไปได้ก่อนหน้านี้) คุณจะต้องrequire 'active_support/core_ext/enumerable'
Dennis

96

ไปเลย:

unless @players.include?(p.name)
  ...
end

คุณอาจดูคู่มือทับทิมสไตล์สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเทคนิคที่คล้ายกัน


โหวตขึ้นสำหรับคำแนะนำเกี่ยวกับสไตล์ แค่วัสดุการอ่านที่ฉันต้องการ
justnorris

1
สามารถอ่านได้สำหรับหนึ่งคำสั่ง ถ้ามากแล้วใช้ดีกว่าปฏิเสธ! หรือเพิ่มวิธีการของคุณเองเพื่อทับทิมคลาสอาเรย์
Renars Sirotins

3
ต้องการสิ่งนี้ในการยกเว้นหรือไม่ ตอบเพราะมันเป็นทับทิมบริสุทธิ์
dscher

1
แต่ก็ยังแปลกเมื่อทำงานกับสภาพผสม if flag unless @players.include?(p.name)อึดอัดใจและif flag && !@players.include?(p.name)ใช้การปฏิเสธ
gabe

1
ในขณะที่ifปล่อยให้เพียงtrueผ่านสภาพunlessช่วยให้ผ่านและfalse nilบางครั้งสิ่งนี้นำไปสู่การหาข้อบกพร่องยาก ดังนั้นฉันชอบexclude?
ToTenMilan

12

วิธีการเกี่ยวกับต่อไปนี้:

unless @players.include?(p.name)
  ....
end

ผู้ชายด้วยความเร็วที่คำตอบเข้ามาในเว็บไซต์นี้ฉันไม่รู้ว่าฉันจะได้รับชื่อเสียงโดยปราศจากการเลือกที่รักมักที่ชังที่ดี! :-D ลิงค์ Style Guide นั้นน่าประทับใจ
ilasno

2
มันไม่เกี่ยวกับความรวดเร็ว มันเกี่ยวกับการเป็นอย่างละเอียด (ฉันได้พบแล้ว) =)
Charles Caldwell

11

ดูทับทิมเท่านั้น:

TL; DR

ใช้none?ส่งต่อบล็อกด้วย==สำหรับการเปรียบเทียบ:

[1, 2].include?(1)
  #=> true
[1, 2].none? { |n| 1 == n  }
  #=> false

Array#include?ยอมรับหนึ่งอาร์กิวเมนต์และใช้==เพื่อตรวจสอบกับแต่ละองค์ประกอบในอาร์เรย์:

player = [1, 2, 3]
player.include?(1)
 #=> true

Enumerable#none?ยังสามารถยอมรับหนึ่งอาร์กิวเมนต์ในกรณีที่มันใช้===สำหรับการเปรียบเทียบ เพื่อให้ได้พฤติกรรมที่ตรงข้ามกับinclude?เราเราจะละเว้นพารามิเตอร์และส่งมันเป็นบล็อกที่ใช้==สำหรับการเปรียบเทียบ

player.none? { |n| 7 == n }
 #=> true 
!player.include?(7)    #notice the '!'
 #=> true

ในตัวอย่างข้างต้นเราสามารถใช้จริง:

player.none?(7)
 #=> true

นั่นเป็นเพราะInteger#==และInteger#===เทียบเท่า แต่พิจารณา:

player.include?(Integer)
 #=> false
player.none?(Integer)
 #=> false

none?ผลตอบแทนเพราะfalse Integer === 1 #=> trueแต่จริงๆ Legit วิธีควรกลับnotinclude? trueอย่างที่เราเคยทำมาก่อน:

player.none? { |e| Integer == e  }
 #=> true

7
module Enumerable
  def does_not_include?(item)
    !include?(item)
  end
end

ตกลง แต่อย่างจริงจังเว้นแต่จะได้ผลดี


1
+1 unlessไม่เป็นไรสำหรับตัวอย่างที่แสดง แต่สภาพอาจซับซ้อนกว่านี้ ฉันคิดว่ามันมีประโยชน์ที่จะมีวิธีที่ทำให้ไร้ผลเหล่านี้พวกเขาอนุญาตให้มีรหัสที่เปิดเผยมากขึ้น
tokland


1

คุณสามารถใช้:

unless @players.include?(p.name) do
...
end

unlessเป็นสิ่งที่ตรงกันข้ามหรือคุณอาจจะใช้ifreject

คุณสามารถrejectองค์ประกอบที่ไม่จำเป็น:

@players.reject{|x| x==p.name}

หลังจากได้รับผลลัพธ์คุณสามารถใช้งานได้


0

การใช้unlessคำสั่งที่ดีสำหรับประโยคที่มีinclude?คำสั่งเดียวแต่ตัวอย่างเช่นเมื่อคุณต้องการตรวจสอบการรวมบางอย่างในที่เดียวArrayแต่ไม่ได้อยู่ในที่อื่นการใช้include?ด้วยexclude?นั้นง่ายกว่ามาก

if @players.include? && @spectators.exclude? do
  ....
end

แต่ดังที่ dizzy42 กล่าวไว้ข้างต้นการใช้งานexclude?จำเป็นต้องมี ActiveSupport


เพียงต้องการใช้ส่วนขยายหลักของ Active Support guide.rubyonrails.org/v3.2/…
Tin Man


0

ลองสิ่งนี้มันเป็น Ruby บริสุทธิ์ดังนั้นไม่จำเป็นต้องเพิ่มเฟรมเวิร์กอุปกรณ์ต่อพ่วงใด ๆ

if @players.include?(p.name) == false do 
  ...
end

ฉันกำลังดิ้นรนกับตรรกะที่คล้ายกันสองสามวันและหลังจากตรวจสอบฟอรัมหลายแห่งและบอร์ดถาม - ตอบเพื่อประโยชน์เล็กน้อยมันกลับกลายเป็นว่าวิธีแก้ปัญหานั้นง่ายมาก


0

ฉันค้นหาสิ่งนี้ด้วยตัวเองค้นพบสิ่งนี้จากนั้นก็หาทางแก้ไข ผู้คนใช้วิธีการที่สับสนและวิธีการบางอย่างที่ไม่สามารถใช้งานได้ในบางสถานการณ์หรือไม่ได้เลย

ฉันรู้ว่ามันสายเกินไปแล้วเมื่อพิจารณาว่าเรื่องนี้โพสต์เมื่อ 6 ปีที่แล้ว แต่หวังว่าผู้เยี่ยมชมในอนาคตจะพบสิ่งนี้ (และหวังว่ามันจะสามารถทำความสะอาดโค้ดของคุณและของคุณได้)

วิธีแก้ปัญหาง่าย ๆ :

if not @players.include?(p.name) do
  ....
end
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.