2016-06-29 3 views
2

배열이 여러 번 배열에 표시되는 개체 배열이 있습니다. 한 항목의 특정 위치에 대한 색인이 있습니다. 색인을 유지하면서 모든 위치의 배열에서 하나의 객체를 삭제하고 싶습니다. 삭제 된 항목의 인덱스는 다음 사용 가능한 항목으로 이동해야하며,없는 경우에는 배열의 시작 부분으로 되돌려 야합니다.배열 보존 색인에서 항목 삭제

array = [:b, :a, :b] 
index = 2 

이제 배열에서 :a을 삭제하고, 두 번째 :b이기 때문에 인덱스가 지금은 1이어야한다 :

나는 그것을 아주 잘 설명하고있어 생각하지 않는다, 그래서 여기에 간단한 예제 이제 인덱스 1에 있습니다.

인덱스가 삭제 된 개체를 가리 키지 만 다음 사용 가능한 개체로 이동해야합니다. 따라서 인덱스가 1이면 :b을 가리키고 바로 다음에 :a이 오므로 변경되지 않습니다. 여기

는 랩 어라운드 예제 :

array = [:b, :a] 
index = 1 

그런 다음 인덱스가 사용 가능한 다음 인덱스 주위에 포장해야 :a을 삭제하는 경우, 또는 0

간단한 것 같은데,하지만 훨씬 더 복잡한 가장자리 경우가 있습니다 . 'A'를, 결과 배열이 [:b, :c, :b]가 삭제 한 후

array = [:a, :a, :b, :a, :c, :b, :a] 

: 여기에 내가 생각할 수있는 가장 복잡한 예입니다. 가능한 모든 시작 인덱스 (0-6)에서 0, 0, 0, 1, 1, 2, 0으로 변경해야합니다.

배열에 개체가 여러 개 있다고 가정하고 삭제 후에는 절대로 비어 있지 않습니다. .

(편집) 내가 지금까지 시도했다 포함해야한다고 나를 알리는 @Raffael에

감사합니다. 여기에 내 첫 시도 :

  • @items은 배열입니다.
  • @current_item_index은 조정해야하는 지수입니다.
  • item은 삭제되는 항목입니다.

코드 :

indexes = @items.each_index.each_with_object([]) do |i, memo| 
    memo << i if @items[i] == item 
end 

indexes.reverse.each do |i| 
    @items.delete_at(i) 
    @current_item_index -= 1 if i < @current_item_index 
    @current_item_index = 0 unless @current_item_index < @items.size 
end 

가 그냥 아주 "루비"를 보이지 않았다 (일반도 간결하지 않음). 또한 목록을 두 번 실행하기 때문에 매우 성과가없는 것처럼 보입니다. 좋지 않을 수도있는 모든 전화 번호는 delete_at입니다.

+1

왜이 작업을 수행하고 있습니까? 즉, 사용 컨텍스트가 무엇입니까? 최종 목표를 달성하기위한 더 좋은 방법이 없을 수 있습니까? – pjs

+0

귀하는이 질문에 40 분 이상 전에 질문했습니다. 대답은 없으며 단 하나의 의견입니다. 즉, 아무도 귀하의 질문을 이해하지 못합니다. 첫 번째 예제에서'index = 2 '인데도 인덱스 1에있는': a'를 삭제합니다. 당신이 그렇게하도록 인도하는 규칙은 무엇입니까? 아마 당신이'index-1'에서 엘리먼트를 지우고 있다고 생각했습니다. 그러나 두 번째 예에서는'index = 1' 일 때 ': b'는 인덱스'index - 1 # => 0'에 있기 때문에 삭제 될 것으로 예상했지만 아니요, 그것은': a'입니다. 색인 1, 삭제됩니다. 질문을 수정하여 명확히하십시오. –

+1

@pjs : 현재 플레이어를 추적 할 수있는 인덱스가있는 게임 플레이어 목록이 있습니다. 플레이어는 여러 번 회전 할 수 있으므로 배열에 여러 번 있습니다. 이 알고리즘은 플레이어가 게임을 종료 할 때 실행되도록 고안되었습니다. 더 나은 표현이 제시되면 표현을 리팩터링하는 것에 전적으로 열려 있습니다. –

답변

1

새로운 인덱스

  • 이전 인덱스의 앞에 배치되어있는 이전 배열 요소의 수와 동일한

하면 셀 수 배열에 남아 다음과 같이 새 배열을 구성하는 동안 이동 중에도 이러한 작업을 수행 할 수 있습니다.

def delete_and_follow(old_array, old_index, unwanted) 
    new_array, new_index = [], 0 
    old_array.each.with_index do |item, idx| 
    unless item == unwanted 
     new_array << item 
     new_index += 1 if idx < old_index 
    end 
    end 
    new_index = 0 if new_index >= new_array.length 
    [new_array, new_index] 
end 

또는 동일한 위트 시간 적은 코드 (비록 좀 더 비밀) :

def delete_and_follow(old_array, old_index, unwanted) 
    new_index = old_array.take(old_index).count{ |item| item != unwanted } 
    new_array = old_array - [unwanted] 
    [new_array, new_index % new_array.length] 
end 

HTH!

+0

이것은 'old_array' 내부 수정을하지 않는다는 것에주의하십시오. 제자리를 선호하는지 알려주세요. – Raffael

+0

이것은 좋아 보인다. 완료되면 이전 배열과 인덱스를 교체했습니다. 내 원래의 시도가 있었고 꽤 못생긴 보였다. –