ruby-on-rails - 将整数数组减少为最长公共(public)前缀数组

标签 ruby-on-rails ruby

我正在处理邮政编码,我想从邮政编码列表中获取“开头为”值。

例如数组

arr = [10000, 10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008, 10009, 10010, 10011]

应该生成一个数组:

out = [1000,10010,10011]

非常感谢任何帮助。我越想问题就越大!

编辑1:添加更多示例 很抱歉给您带来困惑,并感谢您到目前为止的帮助,从您的评论反馈来看,我的问题标题可能不准确。

我想要的是邮政服务中常用的“开头为”语法。基本上,如果您有固定的 5 位数字(美国邮政编码,没有 zip+4),如果涵盖整个范围,例如11000-11999 那么它可以在开头语法中减少到 11。但是,如果该范围内有一个数字(或一组数字)不包括在内。例如11005,那么语法需要返回该范围内的所有数字,直到再次出现公共(public)“开头”。因此,对于该示例,它将是:

[ 11000, 11001, 11002, 11003, 11004, 11006, 11001, 11007, 11008, 11009, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 111, 112, 113, 114, 115, 116, 117, 118, 119 ]

因此,从 11000-11004 和 11006-11009 之间,没有常见的“开头为”数字,因此必须添加确切的数字。而从11010到11999,常用号码可以按上述方法减少。

在此语法中包含字母将是一个巨大的好处,因为它也涵盖了英国邮政编码。然而,这更困难,因为英国邮政编码并不总是连续的,所以我不打算解决这个问题。 5 位美国邮政编码。

最佳答案

代码

def doit(arr)
  a = arr.dup
  loop do
    size = a.size
    a = combine_by_last(a)
    break if a.size == size
  end
  a
end

def combine_by_last(a)
  b = []
  until a.empty?
    move_10 = a.first % 10 == 0 && a.size > 9 && a[9] == a.first + 9
    if move_10
      b << a.shift/10
      a.shift(9) # discard
    else
      b << a.shift
    end        
  end
  b
end

示例

arr = [10000, 10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008, 10009,
       10010, 10011] +
       (11000..11999).to_a +
       [12251, 12252] +
       (12340..12349).to_a

doit arr
  #=> [1000, 10010, 10011, 11, 12251, 12252, 1234] 

说明

代码减少了数组arr分阶段进行,每个邮政编码序列涉及 10 个邮政编码,第一个以 0 结尾,被 10 个邮政编码中的第一个除以 10 取代。 。当无法进一步减少时,该过程终止。例如,如果:

arr = (11000..11999).to_a

它首先会减少为:

(1100..1199).to_a

然后:

(110..119)

然后:

11

我们可以修改doit以实际行动展示这一点。

def doit(arr)
  a = arr.dup
  loop do
    size = a.size
    a = combine_by_last(a)
    puts
    p a 
    break if a.size == size
  end
  a
end

doit arr
  #=> [1000, 10010, 10011, 11, 12251, 12252, 1234]  

[1000,
 10010, 10011,
 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109,
 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119,
 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129,
 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139,
 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149,
 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159,
 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169,
 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179,
 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189,
 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199,
 12251, 12252,
 1234]

[1000, 
 10010, 10011,
 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
 12251, 12252,
 1234]

[1000,
 10010, 10011,
 11,
 12251, 12252,
 1234]

因为邮政编码是唯一且有序的,a[9] == a.first + 9true当且仅当a[0] , a[1] ,..., a[9]是连续值。

表达式:

move_10 = a.first % 10 == 0 && a.size > 9 && a[9] == a.first + 9

可以简化为:

move_10 = a.first % 10 == 0 && a[9] == a.first + 9

因为如果a.size <= 9 , a[9] == a.first + 9将成为nil == a.first + 9 ,这将导致条件返回 false , 正如它应该。然而,这会降低可读性。

关于ruby-on-rails - 将整数数组减少为最长公共(public)前缀数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58193098/

相关文章:

ruby-on-rails - ArgumentError(缺少必需的 :bucket option):

ruby-on-rails - Rails 服务器未启动 -> 找不到 JavaScript 运行时

ruby-on-rails - 使用用户设置为number_to_currency设置单位?

mysql - Ruby on Rails 不在 mysql 数据库 : truncates numbers after , 中存储小数

ruby-on-rails - 无法在 Nitrous.io 上创建数据库

ruby-on-rails - postgresql nextval 生成现有值

ruby-on-rails - Rails 2.4 => 3.0 : ActiveRecord: `add_modifier` : wrong number of arguments (given 3, 预期 2) (ArgumentError)

ruby-on-rails - 将 RoR 部署到 Heroku 和 Sqlite3 失败

ruby-on-rails - 模块/类库

ruby - 如何通过匹配文本来选择节点