2013-05-18 2 views
1

Может кто-нибудь объяснить мне, почему моя первоначальная константа LIST с самого начала получает манипулирование в конце? Я думал, что константа может быть только однажды инициализирована. Я хочу сохранить манипуляции в новом массиве (new_list), не влияя на исходный (LIST).странное рубиновое поведение с константой

$ned = "foo" 
$med = "" 

print LIST = [:nrd, :mrd_y] # -> [:nrd, :mrd_y] 


list = LIST 

new_list = list.delete_if { |element| 
    case element 
    when :nrd then $ned.empty? 
    when :mrd_y then $ned.empty? || $med.empty? 
    end 
} 

print new_list # -> [:nrd] 

print LIST # -> [:nrd] instead of [:nrd, :mrd_y] 

ответ

2

Array#delete_if -> Удаляет все элементы самоуправления, для которых блок оценивает к истине.

$ned = "foo" 
$med = "" 

LIST = [:nrd, :mrd_y] 
p LIST.object_id #=> 84053120 
list = LIST 
p LIST.object_id #=> 84053120 
new_list = list.delete_if { |element| 
    case element 
    when :nrd then $ned.empty? 
    when :mrd_y then $ned.empty? || $med.empty? 
    end 
} 

List и list держит один и тот же объект Array, так как object_id говорит выше. Таким образом, для каждой оценки true из блока delete_if удаляет элемент из объекта, на который ссылается 84053120. Который хранится в LIST и list. так что вы можете использовать ниже:

$ned = "foo" 
$med = "" 

LIST = [:nrd, :mrd_y] 
list = LIST 
new_list = list.dup.delete_if { |element| 
    case element 
    when :nrd then $ned.empty? 
    when :mrd_y then $ned.empty? || $med.empty? 
    end 
} 

p new_list #=>[:nrd] 
p LIST #=>[:nrd, :mrd_y] 

Или (лучше использовать подход Array#reject),

$ned = "foo" 
$med = "" 

list = [:nrd, :mrd_y] 
new_list = list.reject { |element| 
    case element 
    when :nrd then $ned.empty? 
    when :mrd_y then $ned.empty? || $med.empty? 
    end 
} 
p new_list #=>[:nrd] 
p list #=>[:nrd, :mrd_y] 
+0

Вы также можете использовать [ 'reject'] (HTTP: // рубиново-док. org/core-2.0/Array.html # method-i-reject), если это делает логику блока более чистой. Я думаю, что подходы 'select' или' reject' будут такими, какие я ожидал бы увидеть в Ruby-коде. –

+0

@muistooshort вы правы! Я какое-то время забыл про «отказ». Спасибо за указатель. обновлено. –

+0

Спасибо за ваши предложения. в обоих случаях мне больше не понадобится промежуточный шаг 'list = LIST', правый (просто' LIST.reject')? – ericMTR

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