Ruby数组元素去空格后另一数组同步变更的问题排查
问题原因与解决方案
嘿,这个坑我刚学Ruby的时候也踩过!你的问题本质上是Ruby里对象引用和破坏性方法的特性导致的,我给你拆解清楚:
1. 数组赋值是引用传递,不是拷贝
你写Device1 = Device的时候,并没有创建一个和Device内容一样的新数组——而是让Device1这个变量和Device指向了内存里同一个数组对象。就像给同一个房间装了两扇门,不管从哪扇门进去改房间里的东西,另一扇门进去看也会变。
2. gsub!是原地修改的破坏性方法
Ruby里方法名末尾带!的(比如gsub!、sort!)基本都是破坏性方法——它们会直接修改调用这个方法的对象本身,而不是返回一个新的对象。你这里的x.gsub!(' ','')直接修改了数组里的字符串元素,而因为Device和Device1共享同一批字符串对象,所以两个数组的元素都跟着变了。
怎么解决?
根据你的需求,有两种常见的处理方式:
方式一:让两个数组彻底独立(生成新数组)
如果你想修改Device的同时不影响Device1,可以用map配合非破坏性的gsub(不带!)生成一个全新的数组:
Device = ["Washington DC","Newyork","San Diego","Florida"] Device1 = ["Washington DC","Newyork","San Diego","Florida"] # 生成新数组替换原Device,原字符串对象不会被修改 Device = Device.map { |x| x.gsub(' ', '') } puts Device # 输出 ["WashingtonDC","Newyork","SanDiego","Florida"] puts Device1 # 输出 ["Washington DC","Newyork","San Diego","Florida"]
方式二:先做数组元素级拷贝,再修改
如果你一定要用gsub!,那得先给数组里的每个字符串做独立拷贝,避免共享引用:
Device = ["Washington DC","Newyork","San Diego","Florida"] # 给每个字符串生成副本,创建独立的新数组 Device1 = Device.map { |str| str.dup } Device.each do |x| x.gsub!(' ','') puts x end puts Device # 输出修改后的数组 puts Device1 # 输出原数组,不受影响
小提醒
- 以后遇到对象赋值的时候,先想清楚:是要共享同一个对象,还是要创建新的副本;
- 带
!的破坏性方法尽量谨慎使用,除非你明确知道自己要原地修改对象,不然很容易出现这种“莫名其妙”的副作用。
内容的提问来源于stack exchange,提问作者Hameed Basha
相关产品推荐
相关产品推荐

