ตรวจสอบอาร์เรย์ไม่ว่าง: มีอะไรบ้าง


191

ตรวจสอบว่าอาร์เรย์ไม่ว่างเปล่าหรือไม่โดยใช้any?วิธีการ?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

หรือมันจะดีกว่าที่จะใช้unless a.empty??

คำตอบ:


248

any?ไม่เหมือนnot empty?ในบางกรณี

>> [nil, 1].any?
=> true
>> [nil, nil].any?
=> false

จากเอกสาร:

หากไม่ได้รับบล็อก Ruby จะเพิ่มบล็อกโดยปริยายของ {| obj | obj} (นั่นคืออะไร? จะคืนค่าเป็นจริงถ้าอย่างน้อยหนึ่งในสมาชิกคอลเลกชันไม่ได้เป็นเท็จหรือไม่มี)


8
มีฟังก์ชั่นตรงข้ามกับempty?อะไร?
RocketR

12
@RocketR คุณอาจต้องการpresent?วิธีการชำระเงิน
dantheta

15
@dantastic #present?เป็น Rails-only NoMethodError: undefined method 'present?' for Arrayในทับทิมบริสุทธิ์คุณจะได้รับ
RocketR

6
ไม่ว่า Rails เท่านั้นสนับสนุนการใช้งานrequire 'activesupport'สามารถใช้งานได้โดยไม่ต้องรางเพียงแค่ต้อง
Sergio A.

83

ความแตกต่างระหว่างอาร์เรย์ประเมินค่าของมันเป็นtrueหรือถ้ามันว่างเปล่า

วิธีempty?นี้มาจากคลาส Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

มันถูกใช้เพื่อตรวจสอบว่าอาร์เรย์มีบางสิ่งบางอย่างหรือไม่ ซึ่งรวมถึงสิ่งที่ประเมินfalseเช่นและnilfalse

>> a = []
=> []
>> a.empty?
=> true
>> a = [nil, false]
=> [nil, false]
>> a.empty?
=> false
>> a = [nil]
=> [nil]
>> a.empty?
=> false

วิธีany?นี้มาจากโมดูล Enumerable
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

โดยจะใช้ในการประเมินว่า "ใด ๆ" trueค่าในอาร์เรย์ประเมินเพื่อ วิธีการที่คล้ายกันนี้มีnone?, all?และone?ที่พวกเขาทั้งหมดเป็นเพียงแค่ตรวจสอบเพื่อดูว่ากี่ครั้งที่ความจริงอาจจะได้รับการประเมิน ซึ่งไม่เกี่ยวข้องกับจำนวนของค่าที่พบในอาร์เรย์

กรณีที่ 1

>> a = []
=> []
>> a.any?
=> false
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> true

กรณีที่ 2

>> a = [nil, true]
=> [nil, true]
>> a.any?
=> true
>> a.one?
=> true
>> a.all?
=> false
>> a.none?
=> false

กรณีที่ 3

>> a = [true, true]
=> [true, true]
>> a.any?
=> true
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> false

31

คำนำหน้าคำสั่งที่มีเครื่องหมายอัศเจรีย์จะช่วยให้คุณทราบว่าอาร์เรย์ไม่ว่างเปล่าหรือไม่ ดังนั้นในกรณีของคุณ -

a = [1,2,3]
!a.empty?
=> true

27
การปฏิเสธคู่ คุณจริงจังไหม
3lvis

29
เขาไม่จริงจังเลย!
Alexander Bird

5
ฮิฮิ. การปฏิเสธสองครั้งไม่เหมาะดูเหมือนว่าอ่านได้มากขึ้นในกรณีเฉพาะนี้
Denny Abraham Cheriyan

12
ลบสองครั้งเป็นส่วนหนึ่งของคำถามเดิม "ตรวจสอบอาร์เรย์ไม่ว่าง" คำถามนี้ตอบคำถาม
mattfitzgerald

30

หลีกเลี่ยงany?อาร์เรย์ขนาดใหญ่

  • any? คือ O(n)
  • empty? คือ O(1)

any? ไม่ได้ตรวจสอบความยาว แต่สแกนอาร์เรย์ทั้งหมดเพื่อหาองค์ประกอบที่เป็นความจริง

static VALUE
rb_ary_any_p(VALUE ary)
{
  long i, len = RARRAY_LEN(ary);
  const VALUE *ptr = RARRAY_CONST_PTR(ary);

  if (!len) return Qfalse;
  if (!rb_block_given_p()) {
    for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
  }
  else {
    for (i = 0; i < RARRAY_LEN(ary); ++i) {
        if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
    }
  }
  return Qfalse;
}

empty? ในทางกลับกันตรวจสอบความยาวของอาร์เรย์เท่านั้น

static VALUE
rb_ary_empty_p(VALUE ary)
{
  if (RARRAY_LEN(ary) == 0)
    return Qtrue;
  return Qfalse;
}

ความแตกต่างนั้นมีความเกี่ยวข้องหากคุณมีอาร์เรย์ "กระจัดกระจาย" ที่เริ่มต้นด้วยnilค่าจำนวนมากเช่นเช่นอาร์เรย์ที่เพิ่งสร้างขึ้น


ในกรณีการใช้งานความแตกต่างนั้นมีความเกี่ยวข้องเฉพาะเมื่อคุณมีอาร์เรย์ "กระจัดกระจาย" ที่เริ่มต้นด้วยnilค่าจำนวนมากโดยมีอาร์เรย์ "ปกติ" ที่any?ไม่มีบล็อกส่งคืนที่องค์ประกอบแรกดังนั้นความซับซ้อนยังคงเป็น O (1) เช่นเดียวกับempty?วิธีการ
เดวิด Costa

4

ฉันจะแนะนำให้ใช้unlessและblankตรวจสอบว่าว่างเปล่าหรือไม่

ตัวอย่าง:

unless a.blank?
  a = "Is not empty"
end

นี้จะรู้ว่า 'a' ว่างเปล่าหรือไม่ หาก 'a' ว่างเปล่ารหัสด้านล่างจะไม่ทำงาน


4
#blank?เป็นส่วนหนึ่งของ Rails หากพวกเขากำลังอยู่แล้วโดยใช้ทางรถไฟ#present?เป็นผลทางลบของการ#blank?อยู่แล้ว
Eva

0

ฉันไม่คิดว่ามันจะไม่ดีany?เลย ฉันใช้มันมาก มันชัดเจนและรัดกุม

อย่างไรก็ตามถ้าคุณมีความกังวลเกี่ยวกับnilค่าทั้งหมดที่ถูกโยนออกไปคุณจะถามว่าอาร์เรย์มีsize > 0หรือไม่ ในกรณีนี้ส่วนขยายที่เรียบง่ายแบบตาย ๆ (ไม่ได้รับการปรับให้เหมาะสมที่สุด, แบบลิง) จะช่วยให้คุณเข้าใกล้

Object.class_eval do

  def size?
    respond_to?(:size) && size > 0
  end

end

> "foo".size?
 => true
> "".size?
 => false
> " ".size?
 => true
> [].size?
 => false
> [11,22].size?
 => true
> [nil].size?
 => true

นี่เป็นคำอธิบายที่สมเหตุสมผลและมีเหตุผลถามว่า "วัตถุนี้มีขนาดหรือไม่" และกระชับและไม่ต้องใช้ ActiveSupport และง่ายต่อการต่อเติม

ความพิเศษบางอย่างที่ควรคำนึงถึง:

  1. สิ่งนี้ไม่เหมือนกับpresent?จาก ActiveSupport
  2. คุณอาจต้องการรุ่นที่กำหนดเองStringซึ่งละเว้นช่องว่าง (เช่นpresent?นั้น)
  3. คุณอาจต้องการชื่อlength?สำหรับStringหรือชนิดอื่น ๆ ที่มันอาจจะอธิบายเพิ่มเติม
  4. คุณอาจต้องการให้มันกำหนดเองสำหรับIntegerและNumericประเภทอื่น ๆเพื่อให้ศูนย์ตรรกะกลับfalseมา
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.