我正在处理邮政编码,我想从邮政编码列表中获取“开头为”值。
例如数组
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 + 9
是 true
当且仅当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/