golang 왜 우리는 집합 데이터 구조를 가지고 있지 않습니까 [closed]


129

나는 세트가 필요한 "The go programming lanaguage"연습 문제 # 1.4를 풀려고합니다. 집합 유형을 만들 수 있지만 언어에 왜 포함되지 않습니까? 구아바도 시작된 Google에서 왔는데 언어 디자이너가 기본 데이터 구조에 대한 지원을 추가하지 않은 이유는 무엇입니까? 왜 당신의 사용자가 집합처럼 아주 기본적인 것에 대한 자신의 구현을 만들도록 강요합니까?


11
흠. 왜 반대표가 나오는지 궁금하십니까? 저는 제네릭 없이도 처음부터 거의 옳은 세트를 가지고 있던 자바 세계에서 왔습니다. 그래서, 기괴한 릴이 동작 A를 찾을 수
anjanb

답변:


83

부분적으로, Go에는 제네릭이 없기 때문에 (따라서 모든 유형에 대해 하나의 세트 유형이 필요하거나 반사에 폴백하여 다소 비효율적입니다).

부분적으로, "개별 요소를 세트에 추가 / 제거"하고 "상대적으로 공간 효율적"인 경우에는 a를 사용하여 상당한 양을 얻을 수 있습니다 map[yourtype]bool(그리고 세트의 true모든 요소에 대해 값을 로 설정). ) 또는 공간 효율성을 높이기 위해 빈 구조체를 값으로 사용 _, present = the_setoid[key]하고 존재 여부를 확인 하는 데 사용할 수 있습니다.


1
또한 다른 코드에서 세트를 "인라인"하거나 필요할 때 자체 세트 유형을 정의하여 자신의 코드로 작성하는 것이 Go의 정신에있는 것 같습니다. 어쨌든, 예를 들어 C ++에서 std :: set <T>를 사용하는 것은 항상 함수 구현의 일부로 발생하거나 다른 데이터 구조를 구현합니다. 따라서 맵과 슬라이스 및 필요한 다른 빌딩 블록을 사용하여 다른 데이터 구조를 직접 구현하십시오. 집합의 각각의 사용은 :) 어쨌든 약간 다르게 그것을 사용하는 것입니다
Bjarke 에베르트

1
그러나 일반적으로 set <Foo> 자체가 실제로 필요하지는 않으며 더 큰 것을 구현할 때 set <Foo>를 사용합니다. "재사용 가능"구성 요소를 포함하기 위해 수행해야하는 작업이 단순히 필요를 피하는 것보다 훨씬 더 나쁜 코드를 많이 보았습니다. 그래서 여기에 set <Foo>가 있습니다. 저기있는 함수에는 set <Bar>가 필요합니다. 아직 공분산이 있습니까? 아니면 WrapperFactory를 만들어이 일을 이와 같이 보이게 만드는 것은 어떻습니까? 멤버십을 확인할 수있는 인터페이스가 필요하므로 set <Foo>를 보내지 마십시오.
Bjarke Ebert 2015

42
그렇다면 제네릭이 없다면 '제네릭'맵은 어떻게 구현됩니까?
Fermin Silva

26
바이트를 저장하려면 map[T]struct{}대신을 사용할 수 있습니다 map[T]bool.
emersion


69

한 가지 이유는 맵에서 세트를 생성하기가 쉽기 때문입니다.

s := map[int]bool{5: true, 2: true}
_, ok := s[6] // check for existence
s[8] = true // add element 
delete(s, 2) // remove element

노동 조합

s_union := map[int]bool{}
for k, _ := range s1{
    s_union[k] = true
}
for k, _ := range s2{
    s_union[k] = true
}

교차로

s_intersection := map[int]bool{}
for k,_ := range s1 { 
  if s2[k] {
    s_intersection[k] = true
  }
}

다른 모든 집합 연산을 구현하는 것은 실제로 그렇게 어렵지 않습니다.


10
존재를 확인하는 것은 단순히지도를 색인하는 것입니다. 그 안에 없으면 0 값 ( false)이 적절하게 알려줍니다. 테스트를 위해 쉼표 관용구가 필요하지 않습니다.
icza

2
교차로의 구현은 차이점과 비슷합니다.
musiphil

1
@Kittsil 감사합니다. 업데이트되었습니다.
Salvador Dali

34
빈 구조체가 메모리에서 0 바이트를 차지하기 때문에 map[int]struct{}대신 사용 하는 것이 더 최적 bool입니다. 나는 최근에 이것에 대한 요점을 작성했습니다 gist.github.com/bgadrian/cb8b9344d9c66571ef331a14eb7a2e80
BG 아드리안에게

13
그렇게 쉽지는 않습니다. Set을 사용해야하는 모든 곳에 코드를 작성하는 것만으로도 요즘 나에게는 우스꽝스러워 보입니다. 컬렉션 지원은 모든 언어로 제공되어야합니다. 더 나은 대답은 Go가 아직 성숙하지 않다는 것입니다. 나는 곧 그것을 다룰 도서관이있을 것이라고 확신한다.
스테프

5

Vatine이 쓴 것처럼 : go에는 제네릭이 없기 때문에 표준 라이브러리가 아닌 언어의 일부 여야합니다. 이를 위해 키워드 세트, 공용체, 교차점, 차이, 하위 집합 등으로 언어를 오염시켜야합니다.

다른 이유는 세트의 "올바른"구현이 무엇인지 전혀 명확하지 않기 때문입니다.

  1. 기능적 접근 방식이 있습니다.

    func IsInEvenNumbers(n int) bool {
        if n % 2 == 0 {
            return true
        }
       return false
    }
    

이것은 모든 짝수 정수의 집합입니다. 매우 효율적인 조회 및 결합, 교차, 차이 및 하위 집합을 기능 구성으로 쉽게 수행 할 수 있습니다.

  1. 아니면 달리가 보여준 것처럼 has-like 접근 방식을 사용합니다.

값과 관련된 무언가를 저장하기 때문에 맵에는 그 문제가 없습니다.


2
내장 세트를 처리하기 위해 Pascal +은 합집합, -차이, *교차, <=하위 집합, >=상위 집합, =동등성, <>부등식 및 in멤버십 과 같은 이진 (두 인수) 연산자를 오버로드합니다 . 따라서 Go에서는 하나의 새 키워드 인 in. 반면에 Pascal의 내장 세트는 "ordinals", 즉 특정 크기의 정수 값을 기본으로 표현하는 모든 유형에서만 작동합니다.
kostix

9
세트를 구현하는 여러 가지 방법이 있다는 사실은 다른 많은 언어에서 제공하는 것을 막지 못했습니다.
augurar

@kostix : 이동 심지어 구문을 사용할 수 있습니다 s[key](마치이 s이었다 map[T]bool대신) key in s.
musiphil

2
단순히 돌아 오지 않는 이유는 n % 2 == 0무엇입니까?
João Andrade

4

또 다른 가능성은 하나 이상의 패키지 가있는 비트 세트를 사용 하거나 내장 된 패키지를 사용할 수 있습니다 . 이 경우 기본적으로 개체를 인덱스로 변환하는 방법을 정의해야합니다.


1
위에서 언급 한 bitset 패키지의 원래 버전을 작성했습니다.
Will Fitzgerald
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.