Ruby-배열을 비교하고 조건에 따라 인덱스를 얻습니다.

Aug 18 2020

두 개의 배열이 있습니다

array_input = %w[one two three two]
array_compare = %w[one two three four five]

값이 입력 배열에있는 경우 array_compare 배열에서 '가장 높은'인덱스를 추출하고 싶습니다. 원하는 출력은 입력 배열과 배열에있는 2것과 같습니다 .threecompare

난 노력 했어

val = nil
array_compare.reverse_each do |v|
  val = v and break if array_input.include? v
end

그러나 그것은 val을 설정하지 않습니다.

답변

1 CarySwoveland Aug 19 2020 at 02:30

쓸 수있다

array_compare.rindex { |e| array_input.include?(e) }
  #=> 2

그러나 일치를 찾을 때까지 (마지막부터 시작하여)의 array_input각 요소 에 대한 선형 검색이 필요합니다 array_compare. 다음이 더 좋습니다.

array_compare.rindex((array_compare & array_input).last)
  #=> 2

단계는 다음과 같습니다.

a = array_compare & array_input
  #=> ["one", "two", "three"]

Array # &를 참조하십시오 . "순서는 원래 배열 [ array_compare] 에서 유지됩니다 ."에 유의하십시오 . 이 원 패스 작업은 C로 구현되므로 매우 빠릅니다. 계속해서

e = a.last
  #=> "three" 
array_compare.rindex(e)
  #=> 2

Array # rindex를 참조하십시오 .

2 iGian Aug 18 2020 at 22:14

내가 제대로 이해한다면

값이 입력 배열에있는 경우 array_compare 배열에서 '가장 높은'인덱스를 추출합니다.

이것은 옵션이 될 수 있습니다.

array_compare.map.with_index { |e, id| id if array_input.include? e }.compact.max #=> 2

이면 array_compare = %w[one two three four five three]을 반환합니다 5.

2 TimurShtatland Aug 18 2020 at 23:18

더 빠른 조회를 위해 조회에 사용 된 배열을 set로 변환합니다 .
속도를 위해 최대 인덱스를 검색하는 배열의 끝에서 반복하십시오 (올바르게 수행하고 있음). 배열의 시작부터 반복하고 최대 인덱스를 선택하는 솔루션은 일반적으로 마지막 일치 요소를 찾을 때까지 모든 쓸모없는 조회로 인해 느립니다. 아래 방법은 첫 번째 성공적인 경기에서 빠르게 멈 춥니 다.
마지막으로 역방향 배열의 array_compare.reverse.each_with_index인덱스를 반환 하므로 최대 인덱스를 수정합니다 . 결과 코드는 다른 많은 답변보다 길 수 있지만 간단하고 빠릅니다.

require 'set'
array_input = %w[one two three two]
array_compare = %w[one two three four five]
set_input = array_input.to_set
i_max = nil
array_compare.reverse.each_with_index { |x, i| i_max = i and break if set_input.include? x }

# correct the index to count from the beginning of 
# array_compare, not from the end:
i_max = array_compare.length - i_max - 1;

puts i_max; # prints: 2

또한보십시오:

Array.include? 비교적 느립니다. 또한 조회 전용 해시가 필요한 경우 다음 집합을 사용하는 것이 좋습니다.https://stackoverflow.com/a/411164/967621

배열, 집합 및 해시 (벤치 마크 포함)에 대한 속도 비교에 대한 추가 정보 : Ruby에서 Set의 장점

1 TeWu Aug 19 2020 at 18:12

내가 생각 해낼 수있는 가장 성능이 좋은 솔루션은 다음과 같습니다.

def find_last_index(set_input, array_compare)
  (array_compare.length - 1).downto(0) do |i|
    return i if set_input.include?(array_compare[i])
  end
end

인수 set_input는이 Set아니라 Array. 배열을 집합으로 변환하는 것은 의미가 있지만 find_last_index동일한 집합으로 여러 번 호출하려는 경우에만 가능합니다 . 그렇지 세트 (어레이로 변환하는 프로세스 to_set)를 사용하면 얻을 수있는 것보다 더 많은 시간이 소요 Set#include?의 AN을 대신 Array#include?. 따라서 find_last_index한 번만 사용하려면을 호출 find_last_index(array_input.to_set, array_compare)하지 말고 대신 집합을 전혀 사용하지 않는이 버전을 사용하십시오.

def find_last_index(array_input, array_compare)
  (array_compare.length - 1).downto(0) do |i|
    return i if array_input.include?(array_compare[i])
  end
end

이 문제에 대한 다양한 솔루션의 벤치 마크 를보고 싶을 수 있습니다 .

user1934428 Aug 18 2020 at 18:32

방금 irb 에서 코드를 실행 (복사 & 붙여 넣기) val했고 그 후 "3"이되었습니다. val나중에 실제로 검사 했습니까?

p val

? 다음은 내 스크립트의 스크린 샷입니다 .