루비에서 맵과 수집의 차이점은 무엇입니까?


427

나는 이것을 구글 검색했고 불쾌하고 모순 된 의견을 얻었 습니다. 루비 / 레일에서 배열을 map수행하는 collect것과 배열을 수행하는 것 사이에 실제로 차이점이 있습니까?

문서는 어떤을 제안하지 않는 것,하지만 방법이나 성능의 차이는 아마도이 있습니까?


5
mapCode Golf 에서 선호됩니다 .
Cary Swoveland

1
mapCodeGolf에서 선호되는 이유에 대한 설명으로 모든 사람에게 분명하지는 않습니다. collect4 자보다 길지만 map기능이 동일 하기 때문 입니다 .
Jochem Schulenklopper

2
나는 악마의 옹호자를하기 위해 개인적으로 collect더 읽기 쉽고 자연스러운 것을 발견합니다. 레코드를 '수집'하고 X를 레코드한다는 아이디어는 '매핑'을하고 X를 수행하는 것보다 더 자연스러운 의미가 있습니다.
sscirrus

답변:


479

가지 사실에 차이는 없다 map로 C로 구현 rb_ary_collect하고 enum_collect(예. 차이가 map어레이에서 다른 어떤 ENUM에가 있지만 차이 사이 mapcollect).


왜 둘 다 할 mapcollect루비에 존재 하는가? map기능에는 여러 언어로 된 많은 명명 규칙이 있습니다. Wikipedia는 개요를 제공합니다 .

map 함수는 함수형 프로그래밍 언어에서 시작되었지만 오늘날 많은 절차 적, 객체 지향 및 다중 패러다임 언어에서도 지원됩니다 (또는 정의 될 수도 있음). C ++의 표준 템플릿 라이브러리에서는 transformC # (3.0)에서이라고합니다. LINQ 라이브러리는이라는 확장 메소드로 제공됩니다 Select. 맵은 Perl, Python 및 Ruby와 같은 고급 언어에서 자주 사용되는 작업입니다. 이 map세 가지 언어 모두에서 작업이 호출 됩니다. Ruby의 스몰 토크 (Smalltalk) [emphasis mine] 에서도지도 collect별칭이 제공됩니다 . 커먼 리스프는 맵과 유사한 기능을 제공합니다. 여기에 설명 된 동작에 해당하는 것을 호출합니다 mapcar(-car는 CAR 조작을 사용하여 액세스를 나타냄).

루비는 스몰 토크 (Smalltalk) 세계의 프로그래머가 집에서 더 많이 느끼도록 별칭을 제공합니다.


왜 배열과 열거 형에 대해 다른 구현이 있습니까? 열거 형은 일반화 된 반복 구조로, Ruby가 다음 요소가 무엇인지 예측할 수있는 방법이 없습니다 (무한 열거 형을 정의 할 수 있습니다 ( 예 : Prime 참조 )). 따라서 각 연속 요소를 가져 오려면 함수를 호출해야합니다 (일반적으로 이것이 each메소드가 됨).

어레이는 가장 일반적인 모음이므로 성능을 최적화하는 것이 합리적입니다. 루비는 배열의 작동 방식에 대해 많이 알고 있기 때문에 호출 each할 필요는 없지만 간단한 포인터 조작 만 사용할 수 있어 훨씬 빠릅니다.

유사 최적화와 같은 배열 방법 중 다수 존재 zipcount.


13
@ Mark Reed 그러나 SmallTalk에서 나오지 않는 프로그래머는 별명으로 판명되는 두 가지 기능을 사용하여 혼란 스러울 것입니다. 위의 OP와 같은 질문이 발생합니다.
SasQ

10
@SasQ 동의하지 않습니다-이름이 하나만 있으면 전체적으로 더 좋을 것이라고 생각합니다. 그러나이 루비의 다른 별칭을 충분히, 그리고 앨리어싱의 한 기능은 작업 중 멋진 이름과 평행이 없기 때문이다 수집 , 탐지 , 분사을 , 거부 하고, 선택 , 그렇지 않으면로 알려진 ( 지도 , 검색 , 감소 , 거부 (별명이 ) 및 find_all ).
Mark Reed

4
과연. 분명히 루비는 더 자주 별칭 / 동의어를 사용하고 있습니다. 예를 들어, 배열의 요소 번호로 검색 될 수있다 count, length또는 size. 다른 배열의 같은 속성에 대한 단어,하지만 이것에 의해, 루비는 당신이 당신의 코드에 가장 적합한 단어를 선택 할 수 있습니다 : 당신이 원하는 않는 의 항목을 당신이있는 거 수집의 길이 배열, 또는 현재 크기 의 구조. 본질적으로 그것들은 모두 동일하지만 올바른 단어를 선택하면 코드를 더 쉽게 읽을 수 있습니다. 이는 언어의 좋은 속성입니다.
Jochem Schulenklopper

51

나는 그들이 같다고 들었 습니다.

실제로 그것들은 ruby-doc.org의 같은 곳에 문서화되어 있습니다 :

http://www.ruby-doc.org/core/classes/Array.html#M000249

  • ary.collect {| item | 블록} → new_ary
  • ary.map {| item | 블록} → new_ary
  • ary.collect → an_enumerator
  • ary.map → an_enumerator

각자의 각 요소에 대해 블록을 한 번 호출합니다. 블록이 반환 한 값을 포함하는 새 배열을 만듭니다. Enumerable # collect도 참조하십시오.
블록을 지정하지 않으면 열거자가 대신 반환됩니다.

a = [ "a", "b", "c", "d" ]
a.collect {|x| x + "!" }   #=> ["a!", "b!", "c!", "d!"]
a                          #=> ["a", "b", "c", "d"]


13

나는이 질문에 답을하기 위해 벤치 마크 테스트를 수행 한 다음이 게시물을 찾았으므로 내 결과 (다른 답변과 약간 다름)가 있습니다.

벤치 마크 코드는 다음과 같습니다.

require 'benchmark'

h = { abc: 'hello', 'another_key' => 123, 4567 => 'third' }
a = 1..10
many = 500_000

Benchmark.bm do |b|
  GC.start

  b.report("hash keys collect") do
    many.times do
      h.keys.collect(&:to_s)
    end
  end

  GC.start

  b.report("hash keys map") do
    many.times do
      h.keys.map(&:to_s)
    end
  end

  GC.start

  b.report("array collect") do
    many.times do
      a.collect(&:to_s)
    end
  end

  GC.start

  b.report("array map") do
    many.times do
      a.map(&:to_s)
    end
  end
end

그리고 내가 얻은 결과는 다음과 같습니다.

                   user     system      total        real
hash keys collect  0.540000   0.000000   0.540000 (  0.570994)
hash keys map      0.500000   0.010000   0.510000 (  0.517126)
array collect      1.670000   0.020000   1.690000 (  1.731233)
array map          1.680000   0.020000   1.700000 (  1.744398) 

별명은 무료가 아닐까요?


1
이러한 차이가 중요한지 확실하지 않습니다. 재실행시 속도가 다른 결과를 얻습니다 (해시 수집 속도가 느리더라도 어레이 수집 속도가 빨라짐)
murb

10

collectcollect!방법에 별칭 mapmap!그들이 의미로 사용 할 수 있습니다. 다음을 쉽게 확인할 수 있습니다.

Array.instance_method(:map) == Array.instance_method(:collect)
 => true

7

Ruby는 메소드 Array # map을 Array # collect로 별칭 지정합니다. 그들은 상호 교환하여 사용될 수 있습니다. (루비 몽크)

즉, 동일한 소스 코드 :

               static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;

RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
    rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
}
return collect;
}

http://ruby-doc.org/core-2.2.0/Array.html#method-i-map


4
설명서에서 별칭이라고 명시 적으로 밝히기를 바랍니다. 현재 그들은 단순히 서로를 참조하며 둘 다 설명이 약간 다릅니다.
Chris Bloom
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.