배열에 객체가 포함되어 있는지 확인하려면 어떻게합니까?
@horses = []
무작위 말로 채울 배열 이 있습니다.
내 @horses
배열에 이미 포함 된 (존재하는) 말이 포함되어 있는지 어떻게 확인할 수 있습니까?
나는 다음과 같은 것을 시도했다.
@suggested_horses = []
@suggested_horses << Horse.find(:first,:offset=>rand(Horse.count))
while @suggested_horses.length < 8
horse = Horse.find(:first,:offset=>rand(Horse.count))
unless @suggested_horses.exists?(horse.id)
@suggested_horses<< horse
end
end
나도 함께 시도 include?
했지만 문자열 전용이라는 것을 알았습니다. 로 exists?
나는 다음과 같은 오류가 발생합니다 :
undefined method `exists?' for #<Array:0xc11c0b8>
그래서 질문은 내 배열에 이미 "말"이 포함되어 있는지 확인하여 동일한 말로 채우지 않도록하는 방법입니다.
Ruby의 배열에는 exists?
메서드가 없지만 문서에 설명 된include?
메서드 가 있습니다. 같은 것
unless @suggested_horses.include?(horse)
@suggested_horses << horse
end
상자에서 작동해야합니다.
객체의 속성을 확인하여 객체가 배열 내에 있는지 확인 any?
하려면 true 또는 false로 평가되는 블록을 사용 하고 전달할 수 있습니다 .
unless @suggested_horses.any? {|h| h.id == horse.id }
@suggested_horses << horse
end
이유는 간단에서 8 개 개의 서로 다른 번호를 선택하여 그것을 할 0
에 Horse.count
당신의 말을 얻는 것을 사용?
offsets = (0...Horse.count).to_a.sample(8)
@suggested_horses = offsets.map{|i| Horse.first(:offset => i) }
이것은 데이터베이스에 8 마리 미만의 말이있는 경우 무한 루프를 일으키지 않는다는 추가 이점이 있습니다.
참고 : Array#sample
은 1.9의 새로운 기능 (1.8.8에서 제공)이므로 Ruby를 업그레이드 require 'backports'
하거나 shuffle.first(n)
.
#include?
작동해야 하며 문자열뿐만 아니라 일반 객체 에서도 작동합니다 . 예제 코드의 문제는 다음 테스트입니다.
unless @suggested_horses.exists?(horse.id)
@suggested_horses<< horse
end
(를 사용한다고 가정해도 #include?
). id가 아닌 특정 개체를 검색하려고합니다. 따라서 다음과 같아야합니다.
unless @suggested_horses.include?(horse)
@suggested_horses << horse
end
ActiveRecord는 상태 (새로 만들기 / 생성됨) 및 ID 만 확인하도록 개체에 대한 비교 연산자를 재정의 했습니다.
Array의 include?
메서드는 문자열뿐만 아니라 모든 객체를 허용합니다. 이것은 작동합니다.
@suggested_horses = []
@suggested_horses << Horse.first(:offset => rand(Horse.count))
while @suggested_horses.length < 8
horse = Horse.first(:offset => rand(Horse.count))
@suggested_horses << horse unless @suggested_horses.include?(horse)
end
그래서 질문은 내 배열에 이미 "말"이 포함되어 있는지 확인하여 동일한 말로 채우지 않도록하는 방법입니다.
대답은 특정 문자열이나 객체가 있는지 확인하기 위해 배열을 살펴 보는 것과 관련이 있지만 배열이 커질수록 검색 시간이 더 오래 걸리기 때문에 실제로는 잘못된 것입니다.
대신 Hash 또는 Set을 사용하십시오 . 둘 다 특정 요소의 단일 인스턴스 만 허용합니다. Set은 배열에 더 가깝게 동작하지만 단일 인스턴스 만 허용합니다. 이는 컨테이너의 특성으로 인해 중복을 방지하는보다 선제적인 접근 방식입니다.
hash = {}
hash['a'] = nil
hash['b'] = nil
hash # => {"a"=>nil, "b"=>nil}
hash['a'] = nil
hash # => {"a"=>nil, "b"=>nil}
require 'set'
ary = [].to_set
ary << 'a'
ary << 'b'
ary # => #<Set: {"a", "b"}>
ary << 'a'
ary # => #<Set: {"a", "b"}>
Hash는 이름 / 값 쌍을 사용하므로 값이 실제로 사용되지는 않지만 일부 테스트에 따르면 Hash를 사용하면 약간의 추가 속도가있는 것 같습니다.
require 'benchmark'
require 'set'
ALPHABET = ('a' .. 'z').to_a
N = 100_000
Benchmark.bm(5) do |x|
x.report('Hash') {
N.times {
h = {}
ALPHABET.each { |i|
h[i] = nil
}
}
}
x.report('Array') {
N.times {
a = Set.new
ALPHABET.each { |i|
a << i
}
}
}
end
출력되는 내용 :
user system total real
Hash 8.140000 0.130000 8.270000 ( 8.279462)
Array 10.680000 0.120000 10.800000 ( 10.813385)
이 ...
horse = Horse.find(:first,:offset=>rand(Horse.count))
unless @suggested_horses.exists?(horse.id)
@suggested_horses<< horse
end
아마 이것이어야 ...
horse = Horse.find(:first,:offset=>rand(Horse.count))
unless @suggested_horses.include?(horse)
@suggested_horses<< horse
end
참고 URL : https://stackoverflow.com/questions/3343861/how-do-i-check-to-see-if-my-array-includes-an-object
'program tip' 카테고리의 다른 글
프로덕션 JavaScript 코드에 "console.log ()"호출을 남겨 두는 것이 좋지 않습니까? (0) | 2020.10.23 |
---|---|
MS Ajax에서 사용하기 위해 .NET 문자열을 JavaScript 문자열로 인코딩하는 표준 방법이 있습니까? (0) | 2020.10.23 |
JAX-RS 다중 오브젝트 게시 (0) | 2020.10.23 |
오류 : 'ejs'모듈을 찾을 수 없습니다. (0) | 2020.10.23 |
Tmux의 창 제목 (0) | 2020.10.23 |