개수, 크기, 길이… 루비에서 너무 많은 선택이 있습니까?


140

나는 이것에 대한 확실한 대답을 찾을 수없는 것 같아서 이것을 "n 번째 수준"으로 이해하고 싶습니다 :-)

    a = { "a"=> "Hello", "b"=> "World"}
    a. 카운트 # 2
    a. 크기 # 2
    길이 # 2

    a = [10, 20]
    a. 카운트 # 2
    a. 크기 # 2
    길이 # 2

그래서 어느 것을 사용해야합니까? 하나 이상의 요소가 있는지 알고 싶다면 중요하지 않지만 실제 차이점을 이해하고 싶습니다. 이것은 배열에도 적용됩니다. 나는 같은 결과를 얻습니다.

또한 ActiveRecord와 개수 / 크기 / 길이가 다른 의미를 가지고 있음을 알고 있습니다. 나는 대부분 순수한 루비 (1.92)에 관심이 있지만 누군가 AR의 차이점에 대해 알고 싶다면 그렇게 평가할 것입니다.

감사!


5
발생한 현상을 TMTOWTDI 라고도 합니다. 한 가지 이상의 방법이 있습니다. 이 슬로건은 Perl 커뮤니티에서 나 왔으며 Perl은 Ruby에 영향을 미칩니다.
Andrew Grimm

이들은 일반적으로 서로 별명입니다-그들은 동일합니다. 명심해야 할 한 가지 방법이 있습니다 : Array#nitems. 배열에있는 비 NIL 항목의 수를 반환합니다. 그러나 루비 1.9에서는 더 이상 사용할 수 없습니다
Tilo

답변:


194

배열과 해시 size의 별칭은 length입니다. 그것들은 동의어이며 정확히 같은 일을합니다.

count 보다 다재다능합니다. 요소 또는 술어를 가져와 일치하는 항목 만 계산할 수 있습니다.

> [1,2,3].count{|x| x > 2 }
=> 1

경우에 어디 하지 않습니다계산할 매개 변수를 제공 기본적으로 호출 길이와 동일한 효과가 있습니다. 그러나 성능 차이가있을 수 있습니다.

Array소스 코드에서 거의 똑같은 일을 볼 수 있습니다. 다음은 구현을위한 C 코드입니다 array.length.

static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}

그리고 여기 구현의 관련 부분이 있습니다 array.count.

static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
    long n = 0;

    if (argc == 0) {
        VALUE *p, *pend;

        if (!rb_block_given_p())
            return LONG2NUM(RARRAY_LEN(ary));

        // etc..
    }
}

에 대한 코드 array.count는 몇 가지 추가 검사를 수행하지만 결국 정확히 동일한 코드를 호출합니다 LONG2NUM(RARRAY_LEN(ary)).

반면 해시 ( 소스 코드 )는 자체 최적화 된 버전을 구현하지 않는 count것이므로 Enumerable( 소스 코드 ) 의 구현 이 사용됩니다.이 소스 코드 는 모든 요소를 ​​반복하고 하나씩 계산합니다.

일반적으로 얼마나 많은 요소가 있는지 알고 싶다면 대신 length(또는 별명 size)을 사용하는 것이 좋습니다 count.


액티브와 관련, 다른 한편으로는, 거기에 있는 중요한 차이점은. 이 게시물을 확인하십시오 :


10

데이터베이스 연결을 사용하는 응용 프로그램에는 중요한 차이점이 있습니다.

많은 ORM (ActiveRecord, DataMapper 등)을 사용하는 경우 일반적인 이해는 .size가 데이터베이스에서 모든 항목을 요청하는 쿼리 ( 'select * from mytable')를 생성 한 다음 항목 수를 제공한다는 것입니다. 결과적으로 .count는 훨씬 빠른 단일 쿼리 ( 'select count (*) from mytable')를 생성합니다.

이러한 ORM은 가장 놀랍게도 원칙에 따라 널리 보급되기 때문입니다. 일반적으로 메모리에 이미 무언가가 있으면 .size를 사용하고 코드에서 데이터베이스 (또는 API를 통한 외부 서비스)에 대한 요청을 생성하면 .count를 사용합니다.


1
이것으로 고려해야 할 것은입니다 counter_cache. 테이블이 있고 foohas_many 인 bar경우 a 가 작성 / 파기 될 때마다 업데이트 되는 foonamed 열이 있습니다 . 를 사용하면 해당 열을 확인하는 것입니다 (실제로 any를 쿼리하지 않고 ). 캐시의 목적을 무효화하는 실제 쿼리를 수행합니다. bars_countbarfoo.bars.sizebarsfoo.bars.count
Dudo

7

대부분의 경우 (예 : Array 또는 String ) size는의 별칭 입니다 length.

count일반적으로 Enumerable 에서 제공되며 선택적 술어 블록을 사용할 수 있습니다. 따라서 enumerable.count {cond}[대략] (enumerable.select {cond}).length-일치하는 술어의 수가 필요하기 때문에 중간 구조를 우회 할 수 있습니다.

참고 : 블록이 지정되지 않았거나 가능한 경우 단락으로 열거되면 열거를 count 강제 로 평가 하는지 확실 하지 않습니다 length.

편집 (및 Mark의 답변 덕분에!) : count 블록이 없으면 (적어도 배열의 경우) 평가를 강제 하지 않습니다 . 나는 술어없이 평가를 강제하는 것이 실제로 어쨌든 합리적이라면 공식적인 행동없이 다른 구현에 대해 "공개적"이라고 생각합니다.


5

http://blog.hasmanythrough.com/2008/2/27/count-length-size 에서 좋은 answare를 찾았습니다.

ActiveRecord에는 연결에 몇 개의 레코드가 있는지 확인하는 몇 가지 방법이 있으며 작동 방식에 약간의 차이가 있습니다.

post.comments.count-SQL COUNT 조회가있는 요소 수를 결정하십시오. 연관된 요소의 서브 세트 만 계산하는 조건을 지정할 수도 있습니다 (예 : : conditions => {: author_name => "josh"}). 연결에 카운터 캐시를 설정하면 #count는 새 쿼리를 실행하는 대신 캐시 된 값을 반환합니다.

post.comments.length-항상 연관 내용을 메모리에로드 한 다음로드 된 요소 수를 반환합니다. 연결이 이전에로드 된 후 다른 방법 (예 : post.comments.create (...) 대신 Comment.create (...))을 통해 새 주석이 작성된 경우에는 업데이트가 적용되지 않습니다.

post.comments.size-이전 두 옵션의 조합으로 작동합니다. 컬렉션이 이미로드 된 경우 #length를 호출하는 것처럼 길이를 반환합니다. 아직로드되지 않은 경우 #count를 호출하는 것과 같습니다.

또한 나는 개인적인 경험이 있습니다.

<%= h(params.size.to_s) %> # works_like_that !
<%= h(params.count.to_s) %> # does_not_work_like_that !

2

우리는 같은 배열에 얼마나 많은 요소를 찾을 수있는 여러 가지 방법을 가지고 .length, .count하고 .size. 그러나 array.size보다 사용하는 것이 좋습니다 array.count. 하기 때문에 .size성능이 더 좋다.


1

Mark Byers 답변에 더 추가하기. Ruby에서이 메소드 array.sizeArray # length 메소드 의 별명 입니다. 이 두 가지 방법을 사용하는 데 기술적 차이는 없습니다. 아마도 성능 차이도 보이지 않을 것입니다. 그러나 array.count동일한 작업을 수행하지만 추가 기능을 가진 Array # count

어떤 조건에 따라 요소를 모두 얻는 데 사용할 수 있습니다. 카운트는 세 가지 방법으로 호출 할 수 있습니다.

Array # count # 배열 의 요소 수를 반환

Array # count n # Array에서 값이 n 인 요소의 수를 반환합니다.

배열 #count {| i | i.even?} 각 요소 배열에서 호출 된 조건에 따라 개수를 반환합니다.

array = [1,2,3,4,5,6,7,4,3,2,4,5,6,7,1,2,4]

array.size     # => 17
array.length   # => 17
array.count    # => 17

여기서 세 가지 방법 모두 동일한 작업을 수행합니다. 그러나 여기에 count흥미로운 곳이 있습니다.

배열에 값 2를 포함하는 배열 요소의 수를 찾고 싶습니다.

array.count 2    # => 3

이 배열에는 값이 2 인 총 3 개의 요소가 있습니다.

이제 4보다 큰 모든 배열 요소를 찾고 싶습니다.

array.count{|i| i > 4}   # =>6

이 배열에는 4보다 큰 총 6 개의 요소가 있습니다.

count방법 에 대한 정보를 제공하기를 바랍니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.