아직없는 경우 배열에 요소 추가


92

루비 클래스가 있습니다

class MyClass
  attr_writer :item1, :item2
end

my_array = get_array_of_my_class() #my_array is an array of MyClass
unique_array_of_item1 = []

에 푸시 MyClass#item1하고 unique_array_of_item1싶지만 아직 unique_array_of_item1포함되지 않은 경우에만 해당됩니다 item1. 내가 아는 간단한 해결책이 있습니다. 반복 my_array하고 unique_array_of_item1이미 현재가 포함되어 있는지 확인하십시오 item1.

더 효율적인 솔루션이 있습니까?

답변:


82

Array 대신 Set 를 사용할 수 있습니다 .


문서에서 세트가 순서가 아니라고 말하는 것은 사실이지만 실제로는 (Ruby 1.9 기준) 순서가 있습니다. 코드를 보면 순서를 가져 오는 데 사용하는 주요 메서드 (예 : Set#eachand Set#to_a)가 @hash. 그리고 Ruby 1.9부터 해시가 주문됩니다. "해시는 해당 키가 삽입 된 순서대로 값을 열거합니다." ruby-doc.org/core-1.9.1/Hash.html
phylae

세트와 같은 것이 없었습니다. 그들은 굉장 정말 감사합니다
브래드

123

@Coorasse 는 다음과 같은 좋은 답변 을 제공합니다.

my_array | [item]

그리고 my_array제자리 에서 업데이트하려면 :

my_array |= [item]

63
또는 my_array |= [item]업데이트 할 my_array장소에
andorov

2
여기에 뭔가 빠졌지 만 | = 연산자가 작동하지 않는 것 같습니까? Ruby 2.1.1
Viet

@Viet |=은 2.1.1의 내 테스트에서 잘 작동합니다. 테스트 사례를 설명하거나 새 질문을여십시오.
depquid

다시 테스트하면 지금 작동합니다. 내 댓글이 몇 달 전에 작성되었으므로 이전에 내가 무엇을했는지 모르겠습니다.
Viet

1
이것의 복잡성은 무엇입니까?
Nobita

40

my_array손 으로 반복 할 필요가 없습니다 .

my_array.push(item1) unless my_array.include?(item1)

편집하다:

Tombart가 그의 의견에서 지적했듯이 사용 Array#include?은 그다지 효율적이지 않습니다. 작은 어레이의 경우 성능에 미치는 영향은 무시할 만하다고 말하고 싶지만 Set더 큰 어레이를 사용하는 것이 좋습니다 .


6
당신은 확실히 그것을하고 싶지 않습니다! array.include?(item)복잡성이 O(n)있으므로 전체 배열을 반복하는 것과 같습니다. 이 벤치 마크를 살펴보십시오 : gist.github.com/deric/4953652
Tombart

32

item1을 배열로 변환하고 결합 할 수 있습니다.

my_array | [item1]

1
이것은해야 |하지 ||(제이슨의 답변을 참조)
세스

1
내 잘못. 죄송합니다. 답 편집
coorasse

3

Set 클래스와 | 메소드 ( "Set Union"이라고도 함)는 고유 한 요소 의 배열을 생성합니다 . 이는 중복을 원하지 않는 경우 좋지만 원래 배열에 디자인 상 고유하지 않은 요소가있는 경우에는 불쾌한 일이 될 것입니다.

원래 배열에 잃고 싶지 않은 중복 요소가 하나 이상있는 경우 조기 반환으로 배열을 반복하는 것은 최악의 경우 O (n)이며, 이는 대규모 계획에서 그리 나쁘지 않습니다. .

class Array
  def add_if_unique element
    return self if include? element
    push element
  end
end

0

완벽한 솔루션인지 확실하지 않지만 나를 위해 일했습니다.

    host_group = Array.new if not host_group.kind_of?(Array)
    host_group.push(host)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.