2016-09-22 3 views
4

У меня есть массив с целыми числами +20000.Эффективный способ сделать добавление на большой массив

Я хочу создать новый массив, в котором каждый элемент в старом массиве добавляется модифицирующее число. На небольшом массиве образцов это будет выглядеть так:

old_array = [2,5,6,8] 
modifying_number = 3 
new_array = [5,8,9,11] 

Есть ли более эффективный способ, чем делать итерацию следующим образом?

class Array 
    def addition_by(x) 
    collect { |n| n + x } 
    end 
end 
+1

Кажется ядро ​​'map' выигрывает день. Теперь вопрос заключается в том, какая реализация Ruby имеет самую быструю «карту»? –

ответ

3

Номер N Итерации - это минимальная сложность этого алгоритма.

Вы можете сделать это на месте, изменив исходный массив на collect! (если вам по каким-то причинам не нужен исходный массив). Сложность будет одинаковой, дополнительный большой объект не будет создан.

+0

хорошее редактирование о модификации места;) –

3

20k записей не очень беспокоиться о производительности.

ary = Array.new(20000) { 1 } 
ary.map! { |el| el + 1 } 

будет работать совершенно нормально.

Я бы просто предложил изменить исходный массив inplace вместо создания нового (используя метод с bang), поэтому он определенно будет использовать меньше ресурсов.

2

Я предполагаю, что это будет означать реализацию map по-другому? This question имеет дело с такой задачей. Я включил тесты ответов от @ JörgWMittag и @uishra. Хотя должно быть сказано, что speed не является обязательным в связанном вопросе, поэтому ответы не могут быть подвергнуты критике в этом отношении. Я также включил ответ @ CarySwoveland на этот вопрос.

require 'fruity' 
require 'matrix' 

class Array 
    #jörg_w_mittag 
    def new_map 
    return enum_for(__callee__) unless block_given? 
    inject([]) {|acc, el| acc << yield(el) } 
    end 

    #uishra 
    def my_map(&block) 
    result = [] 
    each do |element| 
    result << block.call(element) 
    end 
    result 
    end 

    #cary_swoveland 
    def vec_map(k) 
    (Vector[*[k]*self.size] + Vector[*self]).to_a 
    end 

end 

arr = (1..30000).to_a 
k = 3 

10.times do 
    compare do 
    core_map  { ar = arr.dup; ar.map  { |n| n + k } } 
    jörg_w_mittag { ar = arr.dup; ar.new_map { |n| n + k } } 
    uishra   { ar = arr.dup; ar.my_map { |n| n + k } } 
    cary_swoveland { ar = arr.dup; ar.vec_map k } 
    end 
    puts 
end 

Краткое изложение результатов/вывода:

Результаты по пять раз

#Running each test once. Test will take about 1 second. 
#core_map is faster than jörg_w_mittag by 2x ± 1.0 
#jörg_w_mittag is similar to uishra 
#uishra is similar to cary_swoveland 

Результаты в двух случаях

#Running each test once. Test will take about 1 second. 
#core_map is faster than jörg_w_mittag by 2x ± 0.1 
#jörg_w_mittag is similar to uishra 
#uishra is similar to cary_swoveland 

Результаты по три раза

#Running each test once. Test will take about 1 second. 
#core_map is faster than uishra by 2x ± 1.0 
#uishra is similar to jörg_w_mittag 
#jörg_w_mittag is similar to cary_swoveland 
+0

sagar, можете ли вы добавить мой метод к вашему эталону? Я сделал это, и он был привязан к последнему. Кстати, я несколько раз тестировал бенчмарк. Иногда уйшр был быстрее, чем Jörg_W_Mittag, а иногда и нет. Подожди минуту. Где ответ Йерга? –

+0

@CarySwoveland он сравнивал ответы по [связанному вопросу] (http://stackoverflow.com/questions/39609277/create-own-arraymap-like-method) :) –

+0

@CarySwoveland Я обновил тесты. Мой первоначальный ответ (как и этот ответ) включал ответ Йорга, но я только немного изменил его имя метода, но реализация была такой же. Если вы чувствуете, что мне нужно улучшить свой ответ, дайте мне знать. И кстати я впервые обнаружил 'fruity.rb' из одного из ваших предыдущих ответов SO, поэтому ta для этого! –

1
require 'matrix' 

class Array 
    def vec_map(k) 
    (Vector[*[k]*self.size] + Vector[*self]).to_a 
    end 
end 

[1,2,3].vec_map 4 
    #=> [5, 6, 7] 
Смежные вопросы