Kiểm tra mảng không trống: nào?


189

Có phải là xấu khi kiểm tra nếu một mảng không trống bằng cách sử dụng any?phương thức?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

Hoặc nó là tốt hơn để sử dụng unless a.empty??

Câu trả lời:


246

any?không giống như not empty?trong một số trường hợp.

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

Từ tài liệu:

Nếu khối không được đưa ra, Ruby sẽ thêm một khối ẩn {| obj | obj} (đó là bất kỳ? sẽ trả về true nếu ít nhất một trong số các thành viên của bộ sưu tập không sai hoặc không).


8
Có chức năng nào ngược lại empty?không?
RocketR

12
@RocketR bạn có thể muốn kiểm tra present?phương thức.
dantheta

15
@dantastic #present?là chỉ Rails. Trong Ruby thuần túy bạn sẽ nhận được NoMethodError: undefined method 'present?' for Array.
RocketR

6
Không chính xác chỉ có Rails, Active Support có thể được sử dụng mà không cần đường ray, chỉ cần require 'activesupport'.
Sergio A.

82

Sự khác biệt giữa một mảng đánh giá các giá trị của nó đến truehoặc nếu nó trống.

Phương thức empty?này xuất phát từ lớp Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

Nó được sử dụng để kiểm tra xem mảng có chứa thứ gì đó hay không. Điều này bao gồm những thứ đánh giá false, chẳng hạn như nilfalse.

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

Phương pháp any?này xuất phát từ mô-đun En đếm.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

Nó được sử dụng để đánh giá nếu giá trị "bất kỳ" trong mảng đánh giá true. Các phương pháp tương tự như thế này là none?, all?one?, tất cả chúng chỉ cần kiểm tra để xem có thể đánh giá đúng bao nhiêu lần. không liên quan gì đến số lượng giá trị được tìm thấy trong một mảng.

trường hợp 1

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

trường hợp 2

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

trường hợp 3

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

31

Tiền tố câu lệnh với dấu chấm than sẽ cho bạn biết liệu mảng đó có trống không. Vì vậy, trong trường hợp của bạn -

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

27
Phủ định kép? Bạn nghiêm túc chứ?
3lvis

29
Anh như vậy không nghiêm trọng!
Alexander Bird

5
Hehe. Phủ định kép là không lý tưởng, chỉ có vẻ dễ đọc hơn trong trường hợp cụ thể này.
Denny Abraham Cheriyan

11
Tiêu cực kép là một phần của câu hỏi ban đầu "Kiểm tra mảng không trống". Điều này trả lời câu hỏi.
mattfitzgerald

30

Tránh any?cho mảng lớn.

  • any?O(n)
  • empty?O(1)

any? không kiểm tra độ dài nhưng thực sự quét toàn bộ mảng để tìm các phần tử trung thực.

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? mặt khác chỉ kiểm tra độ dài của mảng.

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

Sự khác biệt có liên quan nếu bạn có các mảng "thưa thớt" bắt đầu bằng nhiều nilgiá trị, ví dụ như một mảng vừa được tạo.


Trong trường hợp sử dụng này, sự khác biệt chỉ có liên quan nếu bạn có các mảng "thưa thớt" bắt đầu bằng nhiều nilgiá trị, với các mảng "bình thường" any?không có trả về khối ở phần tử đầu tiên, vì vậy độ phức tạp vẫn là O (1) như empty?phương thức
David Costa

4

Tôi sẽ đề nghị sử dụng unlessblankkiểm tra xem có trống hay không.

Thí dụ :

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

Điều này sẽ biết 'a' trống hay không. Nếu 'a' trống thì đoạn mã dưới đây sẽ không chạy.


4
#blank?là một phần của Rails. Nếu họ đã sử dụng Rails, dù sao đi nữa , đó #present?là sự phủ định #blank?.
Eva

0

Tôi không nghĩ nó tệ khi sử dụng any?. Tôi sử dụng nó rất nhiều. Nó rõ ràng và súc tích.

Tuy nhiên nếu bạn lo lắng về tất cả các nilgiá trị loại bỏ nó, thì bạn thực sự đang hỏi liệu mảng đó có không size > 0. Trong trường hợp đó, phần mở rộng đơn giản đã chết này (KHÔNG được tối ưu hóa, kiểu khỉ) sẽ giúp bạn tiến gần hơn.

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

Điều này khá mô tả, hỏi một cách logic "đối tượng này có kích thước không?". Và nó súc tích, và nó không yêu cầu ActiveSupport. Và thật dễ dàng để xây dựng.

Một số bổ sung để suy nghĩ về:

  1. Điều này không giống như present?từ ActiveSupport.
  2. Bạn có thể muốn có một phiên bản tùy chỉnh cho String, bỏ qua khoảng trắng (giống như present?).
  3. Bạn có thể muốn tên length?cho Stringhoặc các loại khác, nơi nó có thể được mô tả nhiều hơn.
  4. Bạn có thể muốn nó tùy chỉnh cho Integercác Numericloại khác, để trả về số 0 hợp lý false.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.