2012-01-09 4 views
3

У меня есть массив с разными идентификаторами, идущий от 1 до 4000. Мне нужно добавить некоторые элементы в базу данных с идентификатором, который будет проходить в этом массиве. Поскольку наибольший возможный идентификатор - 4000 (это не так много в моем случае), я бы хотел найти самый низкий неиспользованный идентификатор, который мог бы использовать для моего нового элемента.Ruby: Поиск самого низкого свободного ID в массиве ID

Я бы знал, как это сделать на C++, но так как я довольно новый в Ruby, я прошу о помощи. в C++ я бы написал цикл, в котором я бы проверил, будет ли массив [i] == array [i + 1] - 1. Если это не так, то новым id будет массив [i] + 1.

У меня нет идеи, как написать это в Ruby.

Большое спасибо за помощь.

+0

Это приводит к идентификатору 1 со ссылкой на яблоки в январе, но, возможно, бананы в феврале. Обычная процедура позволяет базе данных управлять идентификатором collumn. Тот факт, что у вас максимум 4000, похоже, что у идентификатора есть смысл (например, 0-4000 - это категория продуктов, 4001-5000 - игрушки) - плохая идея. – steenslag

ответ

5
array = [1, 2, 3, 5, 6] 
(1..4000).to_a.-(array).min 
+0

+1 @sawa, очень красиво и лаконично. Должно выполняться очень быстро. –

+0

@theTinMan Спасибо, оловянный человек. – sawa

+0

это действительно очень, очень умно – maprihoda

3
def first_unused_id(ids) 
    index = ids.each_index.find{|i| ids[i] + 1 != ids[i+1] } 
    ids[index] + 1 
end 

Некоторые пояснения:

  • each_index преобразует массив в Enumerator давая индексы массивов.
  • find вернет первый элемент, который возвращает true из переданного ему блока.
6

Использование диапазона, вы можете найти первый элемент, который не является частью вашего массива:

array = [1,2,3,5,6] 
(1..4000).find { |i| !array.include?(i) } 
# => 4 
+1

Это может быть очень неэффективно, потому что включить? метод можно было назвать много тысяч раз (это квадратичная сложность) – maprihoda

+0

Да, определенно некоторая медлительность, чем выше первый доступный идентификатор (когда он «3999, там заметная задержка»). Другие ответы касаются этого. –

0

как об этом один:

(1..4000).find { |i| array[i-1] != i } 

похож на ответ Дилана, но в этом case, он просто проверяет, является ли [n-1] -й член массива n. Если нет, этот индекс «открыт» и возвращается. Это решение требует только один чек за индексом, а не 4000 ...

так для

array = [1,2,3,5,6] 

это будет найти этот массив [4-1]! = 4 (так как массив [3] = 5) и return 4 как первый доступный идентификатор.

(это требует отсортированный массив индексов, но это предполагалось до сих пор)

+1

Это будет отключено одним - 'array [0]' будет 1, а не 0; это должно быть 'array [i-1]'. Кроме того, код, который вы опубликовали, не работает вообще, как есть, поскольку '! Array [i]' всегда будет 'false'. Это должно быть 'array [i-1]! = I' –

+0

спасибо Дилан! изм. – elijah

0
array = [1, 2, 3, 5, 6] 

def lowest_unused(ids) 
    ids.find { |e| ids.index(e) + 1 != e } - 1 
end 

p lowest_unused(array) # 4 
+0

похож на ответ Якуба Хамбла, но немного проще – maprihoda

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