2013-05-18 3 views
1

누군가 내 설명을 해줄 수 있습니까? 처음부터 내 원래의 상수 LIST이 결국 조작되고 있습니까? 상수는 한 번 초기화 될 수 있다고 생각했습니다. 원래 배열 (LIST)에 영향을주지 않고 조작을 새로운 배열 (new_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 -> 블록이 true로 평가하는 자기의 모든 요소를 ​​삭제합니다. object_id 같은 Array 객체를 잡고

$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 
} 

Listlist는 상기 말한다. 따라서 각 true 블록 delete_if에서 평가는 84053120으로 참조되는 개체에서 항목을 삭제합니다. LISTlist에 의해 유지됩니다. 그래서 당신이 아래에 사용할 수 있습니다

$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' 접근 방식을 사용할 것으로 생각합니다. –

+0

@muistooshort 네 말이 맞아! 나는 잠시 동안 '거부'를 잊었다. 포인터 주셔서 감사. 지금 업데이트되었습니다. –

+0

제안 해 주셔서 감사합니다. 두 경우 모두 중간 단계'list = LIST'가 더 이상 필요하지 않을 것입니다, 오른쪽 (그냥'LIST.reject')? – ericMTR