2016-06-29 2 views
2

Существует массив объектов, многие из которых появляются в массиве несколько раз. Существует указатель на конкретное местоположение одного элемента. Я хочу удалить один объект из массива во всех местах, сохраняя индекс. Индекс удаляемого элемента должен перейти к следующему доступному элементу, и если его нет, он должен вернуться к началу массива.Удалить элемент из индексов сохранения массива

Я не думаю, что я объясняю это очень хорошо, так вот простой пример:

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

Теперь удалите :a из массива, а теперь индекс должен быть равен 1, так как второй :b является теперь в индексе 1.

Предположим, что указатель указывает на удаленный объект, он должен перейти к следующему доступному объекту. Поэтому, если индексы были равны 1, это не изменится, так как теперь оно будет указывать на :b, который сразу же следует за :a.

Вот оберточного пример:

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

Если удалить :a то индекс должен обернуть вокруг следующего доступного индекса, или 0.

Кажется просто, но есть гораздо более сложная крайние случаи , Вот самый сложный пример, который я мог думать:

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

После удаления «: а», полученный массив [:b, :c, :b]. Из всех возможных начальных индексов (от 0 до 6) они должны измениться на 0, 0, 0, 1, 1, 2, 0.

Предположим, что в массиве имеется более одного объекта, поэтому после удаления он не становится пустым ,

(Edit)

Благодаря @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 минут назад. Нет ответов и только один комментарий. Значит, никто не понимает ваш вопрос. В первом примере вы удаляете ': a', который находится в индексе 1, даже если' index = 2'. Каково правило, которое заставляет вас делать это? Я подумал, что, возможно, вы удаляете элемент в '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 

Или сделать то же самое остроумие h меньше кода (хотя немного более критически):

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

Это выглядит хорошо. Я только что заменил старый массив и индекс, когда закончил. Моя первоначальная попытка была на месте, и она выглядела довольно уродливо. –

Смежные вопросы