Ruby에서 배열에서 중복 요소 제거


325

중복 요소가 포함 된 Ruby 배열이 있습니다.

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

for 루프와 반복을 사용하지 않고 모든 고유 요소를 유지 하면서이 배열에서 모든 중복 요소를 제거하려면 어떻게해야합니까?

답변:


722
array = array.uniq

uniq 모든 중복 요소를 제거하고 배열의 모든 고유 요소를 유지합니다.

이것은 루비 언어의 많은 아름다움 중 하나입니다.


50
아니, 유니크! 배열이 아직 고유하지 않은 경우 메소드는 nil을 리턴합니다. Ex : a = [1,2,3,4] a.uniq-> [1,2,3,4] 그러나 a.uniq! -> nil
duykhoa

15
나는 이것을 루비 언어의 아름다움으로 보지 않을 것입니다 ... 루비 표준 라이브러리의 아름다움입니까? 저를 잘못 이해하지 마십시오, 언어에 대한 아름다운 것들이 많이 있습니다.
저스틴 L.

7
Objective-C, Javascript 및 PHP에서 동일하게 작성하십시오. 그렇다면 루비는 아름다운 언어가 아닙니다.
Adam Waite

3
복잡한 유형에도 적용됩니다. [{how: "are"}, {u:"doing"}, {how: "are"}].uniq => [{:how=>"are"}, {:u=>"doing"}]
Blaskovicz

5
@duykhoa가 말한 것에 대해, uniq! 방법은 nil을 반환,하지만 당신은 보통의 반환에 대해 걱정하지 않는다 .uniq!는 개체 자체에 대한 작업 수행
carpinchosaurio

82

교차로를 반환 할 수 있습니다.

a = [1,1,2,3]
a & a

중복도 삭제됩니다.


12
기능적 으로이 대답은 정확하지만 유닉스를 사용하는 것보다 눈에 잘 띄지 않습니다.
Fiona T

21
나는이 페이지를 방문하는 사람이 다른 방법으로도 그것을 볼 수 있도록 여기에 넣었습니다. 어쨌든 더 낫다고 말하려고하지 않았습니다.
jaredsmith

3
이것이 작동하는 이유는 집합 연산을 사용할 때 결과 배열이 집합으로 취급되기 때문에 일반적으로 반복 값이없는 데이터 구조입니다. a | a(연합)을 사용 하면 동일한 트릭을 수행합니다.
Cezar

47

uniq 메소드를 사용하여 중복 요소를 제거 할 수 있습니다.

array.uniq  # => [1, 2, 4, 5, 6, 7, 8]

알아두면 유용한 uniq것은 블록 을 취한다는 것입니다. 따라서 키 배열이있는 경우 :

["bucket1:file1", "bucket2:file1", "bucket3:file2", "bucket4:file2"]

고유 파일이 무엇인지 알고 싶다면 다음을 사용하여 찾을 수 있습니다.

a.uniq { |f| f[/\d+$/] }.map { |p| p.split(':').last }

5
나는 이것에 약간 혼란스러워합니다. 블록은 자체 비교 함수가 필요한 경우에 사용됩니다. 예를 들어 uniq블록없이 해당 배열로 전송 하면 블록과 동일한 값이 반환됩니다.
hdgarrood

18

누군가가 걱정한다면 또 다른 대안.

또한 to_set배열을 Set으로 변환하는 배열 의 메소드를 사용할 수 있으며 , 정의에 따라 set 요소는 고유합니다.

[1,2,3,4,5,5,5,6].to_set => [1,2,3,4,5,6]

4
메모리에 신경 to_set쓰면 4 개의 객체를 uniq할당하고 1 개의 객체를 할당합니다.
Jan Klimo

18

누군가 반복되는 값의 모든 인스턴스를 제거하는 방법을 찾고 있다면 " 루비 배열에서 반복되는 요소를 효율적으로 추출하려면 어떻게해야합니까? "를 참조하십시오.

a = [1, 2, 2, 3]
counts = Hash.new(0)
a.each { |v| counts[v] += 1 }
p counts.select { |v, count| count == 1 }.keys # [1, 3]

3
아니면 간단하게 할 수 있습니다 a = [1, 2, 2, 3] a.find_all { |x| a.count(x) == 1 } # [1, 3]
Tim Wright

연결된 질문은 동일하지 않습니다. 중복 된 값을 찾아서 반환하는 방법을 묻습니다. OP가 중복을 제거하려고합니다.
틴 남자

0

통찰력을 제공하기 위해 :

require 'fruity'
require 'set'

array = [1,2,2,1,4,4,5,6,7,8,5,6] * 1_000

def mithun_sasidharan(ary)
  ary.uniq
end

def jaredsmith(ary)
  ary & ary
end

def lri(ary)
  counts = Hash.new(0)
  ary.each { |v| counts[v] += 1 }
  counts.select { |v, count| count == 1 }.keys 
end

def finks(ary)
  ary.to_set
end

def santosh_mohanty(ary)
    result = ary.reject.with_index do |ele,index|
      res = (ary[index+1] ^ ele)
      res == 0
    end
end

SHORT_ARRAY = [1,1,2,2,3,1]
mithun_sasidharan(SHORT_ARRAY) # => [1, 2, 3]
jaredsmith(SHORT_ARRAY) # => [1, 2, 3]
lri(SHORT_ARRAY) # => [3]
finks(SHORT_ARRAY) # => #<Set: {1, 2, 3}>
santosh_mohanty(SHORT_ARRAY) # => [1, 2, 3, 1]

puts 'Ruby v%s' % RUBY_VERSION

compare do
  _mithun_sasidharan { mithun_sasidharan(array) }
  _jaredsmith { jaredsmith(array) }
  _lri { lri(array) }
  _finks { finks(array) }
  _santosh_mohanty { santosh_mohanty(array) }
end

실행하면 다음과 같은 결과가 발생합니다.

# >> Ruby v2.7.1
# >> Running each test 16 times. Test will take about 2 seconds.
# >> _mithun_sasidharan is faster than _jaredsmith by 2x ± 0.1
# >> _jaredsmith is faster than _santosh_mohanty by 4x ± 0.1 (results differ: [1, 2, 4, 5, 6, 7, 8] vs [1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, ...
# >> _santosh_mohanty is similar to _lri (results differ: [1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, 7, 8, 5, 6, 1, 2, 1, 4, 5, 6, ...
# >> _lri is similar to _finks (results differ: [] vs #<Set: {1, 2, 4, 5, 6, 7, 8}>)

참고 :이 나쁜 결과를 반환

  • lri(SHORT_ARRAY) # => [3]
  • finks(SHORT_ARRAY) # => #<Set: {1, 2, 3}>
  • santosh_mohanty(SHORT_ARRAY) # => [1, 2, 3, 1]

-4

내장 함수를 사용하지 않고 XOR 연산자를 사용해보십시오.

a = [3,2,3,2,3,5,6,7].sort!

result = a.reject.with_index do |ele,index|
  res = (a[index+1] ^ ele)
  res == 0
end

print result

내장 함수로 :

a = [3,2,3,2,3,5,6,7]

a.uniq

2
나는 downvoted하지 않았고 Ruby에 대해 아무것도 알지 못하지만 .sort!내장 기능도 아닙니다 .
Carolus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.